1ee3c74fbSChris Lattner //===- FileCheck.cpp - Check that File's Contents match what is expected --===// 2ee3c74fbSChris Lattner // 3ee3c74fbSChris Lattner // The LLVM Compiler Infrastructure 4ee3c74fbSChris Lattner // 5ee3c74fbSChris Lattner // This file is distributed under the University of Illinois Open Source 6ee3c74fbSChris Lattner // License. See LICENSE.TXT for details. 7ee3c74fbSChris Lattner // 8ee3c74fbSChris Lattner //===----------------------------------------------------------------------===// 9ee3c74fbSChris Lattner // 10ee3c74fbSChris Lattner // FileCheck does a line-by line check of a file that validates whether it 11ee3c74fbSChris Lattner // contains the expected content. This is useful for regression tests etc. 12ee3c74fbSChris Lattner // 13ee3c74fbSChris Lattner // This program exits with an error status of 2 on error, exit status of 0 if 14ee3c74fbSChris Lattner // the file matched the expected contents, and exit status of 1 if it did not 15ee3c74fbSChris Lattner // contain the expected contents. 16ee3c74fbSChris Lattner // 17ee3c74fbSChris Lattner //===----------------------------------------------------------------------===// 18ee3c74fbSChris Lattner 1991d19d8eSChandler Carruth #include "llvm/ADT/SmallString.h" 2091d19d8eSChandler Carruth #include "llvm/ADT/StringExtras.h" 2191d19d8eSChandler Carruth #include "llvm/ADT/StringMap.h" 2213df4626SMatt Arsenault #include "llvm/ADT/StringSet.h" 23ee3c74fbSChris Lattner #include "llvm/Support/CommandLine.h" 24ee3c74fbSChris Lattner #include "llvm/Support/MemoryBuffer.h" 25ee3c74fbSChris Lattner #include "llvm/Support/PrettyStackTrace.h" 26f08d2db9SChris Lattner #include "llvm/Support/Regex.h" 2791d19d8eSChandler Carruth #include "llvm/Support/Signals.h" 28ee3c74fbSChris Lattner #include "llvm/Support/SourceMgr.h" 29ee3c74fbSChris Lattner #include "llvm/Support/raw_ostream.h" 308879e06dSChris Lattner #include <algorithm> 31981af002SWill Dietz #include <cctype> 32e8b8f1bcSEli Bendersky #include <map> 33e8b8f1bcSEli Bendersky #include <string> 34a6e9c3e4SRafael Espindola #include <system_error> 35e8b8f1bcSEli Bendersky #include <vector> 36ee3c74fbSChris Lattner using namespace llvm; 37ee3c74fbSChris Lattner 38ee3c74fbSChris Lattner static cl::opt<std::string> 39ee3c74fbSChris Lattner CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required); 40ee3c74fbSChris Lattner 41ee3c74fbSChris Lattner static cl::opt<std::string> 42ee3c74fbSChris Lattner InputFilename("input-file", cl::desc("File to check (defaults to stdin)"), 43ee3c74fbSChris Lattner cl::init("-"), cl::value_desc("filename")); 44ee3c74fbSChris Lattner 4513df4626SMatt Arsenault static cl::list<std::string> 4613df4626SMatt Arsenault CheckPrefixes("check-prefix", 47ee3c74fbSChris Lattner cl::desc("Prefix to use from check file (defaults to 'CHECK')")); 48ee3c74fbSChris Lattner 492c3e5cdfSChris Lattner static cl::opt<bool> 502c3e5cdfSChris Lattner NoCanonicalizeWhiteSpace("strict-whitespace", 512c3e5cdfSChris Lattner cl::desc("Do not treat all horizontal whitespace as equivalent")); 522c3e5cdfSChris Lattner 5356ccdbbdSAlexander Kornienko static cl::list<std::string> ImplicitCheckNot( 5456ccdbbdSAlexander Kornienko "implicit-check-not", 5556ccdbbdSAlexander Kornienko cl::desc("Add an implicit negative check with this pattern to every\n" 5656ccdbbdSAlexander Kornienko "positive check. This can be used to ensure that no instances of\n" 5756ccdbbdSAlexander Kornienko "this pattern occur which are not matched by a positive pattern"), 5856ccdbbdSAlexander Kornienko cl::value_desc("pattern")); 5956ccdbbdSAlexander Kornienko 601b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput( 611b9f936fSJustin Bogner "allow-empty", cl::init(false), 621b9f936fSJustin Bogner cl::desc("Allow the input file to be empty. This is useful when making\n" 631b9f936fSJustin Bogner "checks that some error message does not occur, for example.")); 641b9f936fSJustin Bogner 6585913ccaSJames Y Knight static cl::opt<bool> MatchFullLines( 6685913ccaSJames Y Knight "match-full-lines", cl::init(false), 6785913ccaSJames Y Knight cl::desc("Require all positive matches to cover an entire input line.\n" 6885913ccaSJames Y Knight "Allows leading and trailing whitespace if --strict-whitespace\n" 6985913ccaSJames Y Knight "is not also passed.")); 7085913ccaSJames Y Knight 7113df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator; 7213df4626SMatt Arsenault 7374d50731SChris Lattner //===----------------------------------------------------------------------===// 7474d50731SChris Lattner // Pattern Handling Code. 7574d50731SChris Lattner //===----------------------------------------------------------------------===// 7674d50731SChris Lattner 7738820972SMatt Arsenault namespace Check { 7838820972SMatt Arsenault enum CheckType { 7938820972SMatt Arsenault CheckNone = 0, 8038820972SMatt Arsenault CheckPlain, 8138820972SMatt Arsenault CheckNext, 8201ac1707SDuncan P. N. Exon Smith CheckSame, 8338820972SMatt Arsenault CheckNot, 8438820972SMatt Arsenault CheckDAG, 8538820972SMatt Arsenault CheckLabel, 860a4c44bdSChris Lattner 87eba55822SJakob Stoklund Olesen /// MatchEOF - When set, this pattern only matches the end of file. This is 88eba55822SJakob Stoklund Olesen /// used for trailing CHECK-NOTs. 89*a908e7bdSPaul Robinson CheckEOF, 90*a908e7bdSPaul Robinson /// CheckBadNot - Found -NOT combined with another CHECK suffix. 91*a908e7bdSPaul Robinson CheckBadNot 9238820972SMatt Arsenault }; 9338820972SMatt Arsenault } 94eba55822SJakob Stoklund Olesen 9538820972SMatt Arsenault class Pattern { 9638820972SMatt Arsenault SMLoc PatternLoc; 9791a1b2c9SMichael Liao 9838820972SMatt Arsenault Check::CheckType CheckTy; 9991a1b2c9SMichael Liao 100b16ab0c4SChris Lattner /// FixedStr - If non-empty, this pattern is a fixed string match with the 101b16ab0c4SChris Lattner /// specified fixed string. 102221460e0SChris Lattner StringRef FixedStr; 103b16ab0c4SChris Lattner 104b16ab0c4SChris Lattner /// RegEx - If non-empty, this is a regex pattern. 105b16ab0c4SChris Lattner std::string RegExStr; 1068879e06dSChris Lattner 10792987fb3SAlexander Kornienko /// \brief Contains the number of line this pattern is in. 10892987fb3SAlexander Kornienko unsigned LineNumber; 10992987fb3SAlexander Kornienko 1108879e06dSChris Lattner /// VariableUses - Entries in this vector map to uses of a variable in the 1118879e06dSChris Lattner /// pattern, e.g. "foo[[bar]]baz". In this case, the RegExStr will contain 1128879e06dSChris Lattner /// "foobaz" and we'll get an entry in this vector that tells us to insert the 1138879e06dSChris Lattner /// value of bar at offset 3. 1148879e06dSChris Lattner std::vector<std::pair<StringRef, unsigned> > VariableUses; 1158879e06dSChris Lattner 116e8b8f1bcSEli Bendersky /// VariableDefs - Maps definitions of variables to their parenthesized 117e8b8f1bcSEli Bendersky /// capture numbers. 118e8b8f1bcSEli Bendersky /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 1. 119e8b8f1bcSEli Bendersky std::map<StringRef, unsigned> VariableDefs; 1208879e06dSChris Lattner 1213b40b445SChris Lattner public: 1223b40b445SChris Lattner 12338820972SMatt Arsenault Pattern(Check::CheckType Ty) 12438820972SMatt Arsenault : CheckTy(Ty) { } 12574d50731SChris Lattner 1260b707eb8SMichael Liao /// getLoc - Return the location in source code. 1270b707eb8SMichael Liao SMLoc getLoc() const { return PatternLoc; } 1280b707eb8SMichael Liao 12913df4626SMatt Arsenault /// ParsePattern - Parse the given string into the Pattern. Prefix provides 13013df4626SMatt Arsenault /// which prefix is being matched, SM provides the SourceMgr used for error 13113df4626SMatt Arsenault /// reports, and LineNumber is the line number in the input file from which 13213df4626SMatt Arsenault /// the pattern string was read. Returns true in case of an error, false 13313df4626SMatt Arsenault /// otherwise. 13413df4626SMatt Arsenault bool ParsePattern(StringRef PatternStr, 13513df4626SMatt Arsenault StringRef Prefix, 13613df4626SMatt Arsenault SourceMgr &SM, 13713df4626SMatt Arsenault unsigned LineNumber); 1383b40b445SChris Lattner 1393b40b445SChris Lattner /// Match - Match the pattern string against the input buffer Buffer. This 1403b40b445SChris Lattner /// returns the position that is matched or npos if there is no match. If 1413b40b445SChris Lattner /// there is a match, the size of the matched string is returned in MatchLen. 1428879e06dSChris Lattner /// 1438879e06dSChris Lattner /// The VariableTable StringMap provides the current values of filecheck 1448879e06dSChris Lattner /// variables and is updated if this match defines new values. 1458879e06dSChris Lattner size_t Match(StringRef Buffer, size_t &MatchLen, 1468879e06dSChris Lattner StringMap<StringRef> &VariableTable) const; 147b16ab0c4SChris Lattner 148e0ef65abSDaniel Dunbar /// PrintFailureInfo - Print additional information about a failure to match 149e0ef65abSDaniel Dunbar /// involving this pattern. 150e0ef65abSDaniel Dunbar void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 151e0ef65abSDaniel Dunbar const StringMap<StringRef> &VariableTable) const; 152e0ef65abSDaniel Dunbar 153f8bd2e5bSStephen Lin bool hasVariable() const { return !(VariableUses.empty() && 154f8bd2e5bSStephen Lin VariableDefs.empty()); } 155f8bd2e5bSStephen Lin 15638820972SMatt Arsenault Check::CheckType getCheckTy() const { return CheckTy; } 15791a1b2c9SMichael Liao 158b16ab0c4SChris Lattner private: 159e8b8f1bcSEli Bendersky bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); 160e8b8f1bcSEli Bendersky void AddBackrefToRegEx(unsigned BackrefNum); 161fd29d886SDaniel Dunbar 162fd29d886SDaniel Dunbar /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of 163fd29d886SDaniel Dunbar /// matching this pattern at the start of \arg Buffer; a distance of zero 164fd29d886SDaniel Dunbar /// should correspond to a perfect match. 165fd29d886SDaniel Dunbar unsigned ComputeMatchDistance(StringRef Buffer, 166fd29d886SDaniel Dunbar const StringMap<StringRef> &VariableTable) const; 16792987fb3SAlexander Kornienko 16892987fb3SAlexander Kornienko /// \brief Evaluates expression and stores the result to \p Value. 16992987fb3SAlexander Kornienko /// \return true on success. false when the expression has invalid syntax. 17092987fb3SAlexander Kornienko bool EvaluateExpression(StringRef Expr, std::string &Value) const; 171061d2baaSEli Bendersky 172061d2baaSEli Bendersky /// \brief Finds the closing sequence of a regex variable usage or 173061d2baaSEli Bendersky /// definition. Str has to point in the beginning of the definition 174061d2baaSEli Bendersky /// (right after the opening sequence). 175061d2baaSEli Bendersky /// \return offset of the closing sequence within Str, or npos if it was not 176061d2baaSEli Bendersky /// found. 17781e5cd9eSAdrian Prantl size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); 1783b40b445SChris Lattner }; 1793b40b445SChris Lattner 1808879e06dSChris Lattner 18113df4626SMatt Arsenault bool Pattern::ParsePattern(StringRef PatternStr, 18213df4626SMatt Arsenault StringRef Prefix, 18313df4626SMatt Arsenault SourceMgr &SM, 18492987fb3SAlexander Kornienko unsigned LineNumber) { 18585913ccaSJames Y Knight bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot; 18685913ccaSJames Y Knight 18792987fb3SAlexander Kornienko this->LineNumber = LineNumber; 1880a4c44bdSChris Lattner PatternLoc = SMLoc::getFromPointer(PatternStr.data()); 1890a4c44bdSChris Lattner 19074d50731SChris Lattner // Ignore trailing whitespace. 19174d50731SChris Lattner while (!PatternStr.empty() && 19274d50731SChris Lattner (PatternStr.back() == ' ' || PatternStr.back() == '\t')) 19374d50731SChris Lattner PatternStr = PatternStr.substr(0, PatternStr.size()-1); 19474d50731SChris Lattner 19574d50731SChris Lattner // Check that there is something on the line. 19674d50731SChris Lattner if (PatternStr.empty()) { 19703b80a40SChris Lattner SM.PrintMessage(PatternLoc, SourceMgr::DK_Error, 19803b80a40SChris Lattner "found empty check string with prefix '" + 19913df4626SMatt Arsenault Prefix + ":'"); 20074d50731SChris Lattner return true; 20174d50731SChris Lattner } 20274d50731SChris Lattner 203221460e0SChris Lattner // Check to see if this is a fixed string, or if it has regex pieces. 20485913ccaSJames Y Knight if (!MatchFullLinesHere && 20585913ccaSJames Y Knight (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && 20685913ccaSJames Y Knight PatternStr.find("[[") == StringRef::npos))) { 207221460e0SChris Lattner FixedStr = PatternStr; 208221460e0SChris Lattner return false; 209221460e0SChris Lattner } 210221460e0SChris Lattner 21185913ccaSJames Y Knight if (MatchFullLinesHere) { 21285913ccaSJames Y Knight RegExStr += '^'; 21385913ccaSJames Y Knight if (!NoCanonicalizeWhiteSpace) 21485913ccaSJames Y Knight RegExStr += " *"; 21585913ccaSJames Y Knight } 21685913ccaSJames Y Knight 2178879e06dSChris Lattner // Paren value #0 is for the fully matched string. Any new parenthesized 21853e0679dSChris Lattner // values add from there. 2198879e06dSChris Lattner unsigned CurParen = 1; 2208879e06dSChris Lattner 221b16ab0c4SChris Lattner // Otherwise, there is at least one regex piece. Build up the regex pattern 222b16ab0c4SChris Lattner // by escaping scary characters in fixed strings, building up one big regex. 223f08d2db9SChris Lattner while (!PatternStr.empty()) { 2248879e06dSChris Lattner // RegEx matches. 22553e0679dSChris Lattner if (PatternStr.startswith("{{")) { 22643d50d4aSEli Bendersky // This is the start of a regex match. Scan for the }}. 227f08d2db9SChris Lattner size_t End = PatternStr.find("}}"); 228f08d2db9SChris Lattner if (End == StringRef::npos) { 229f08d2db9SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 23003b80a40SChris Lattner SourceMgr::DK_Error, 23103b80a40SChris Lattner "found start of regex string with no end '}}'"); 232f08d2db9SChris Lattner return true; 233f08d2db9SChris Lattner } 234f08d2db9SChris Lattner 235e53c95f1SChris Lattner // Enclose {{}} patterns in parens just like [[]] even though we're not 236e53c95f1SChris Lattner // capturing the result for any purpose. This is required in case the 237e53c95f1SChris Lattner // expression contains an alternation like: CHECK: abc{{x|z}}def. We 238e53c95f1SChris Lattner // want this to turn into: "abc(x|z)def" not "abcx|zdef". 239e53c95f1SChris Lattner RegExStr += '('; 240e53c95f1SChris Lattner ++CurParen; 241e53c95f1SChris Lattner 2428879e06dSChris Lattner if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) 2438879e06dSChris Lattner return true; 244e53c95f1SChris Lattner RegExStr += ')'; 24553e0679dSChris Lattner 2468879e06dSChris Lattner PatternStr = PatternStr.substr(End+2); 2478879e06dSChris Lattner continue; 2488879e06dSChris Lattner } 2498879e06dSChris Lattner 2508879e06dSChris Lattner // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* 2518879e06dSChris Lattner // (or some other regex) and assigns it to the FileCheck variable 'foo'. The 2528879e06dSChris Lattner // second form is [[foo]] which is a reference to foo. The variable name 25357cb733bSDaniel Dunbar // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject 2548879e06dSChris Lattner // it. This is to catch some common errors. 25553e0679dSChris Lattner if (PatternStr.startswith("[[")) { 256061d2baaSEli Bendersky // Find the closing bracket pair ending the match. End is going to be an 257061d2baaSEli Bendersky // offset relative to the beginning of the match string. 25881e5cd9eSAdrian Prantl size_t End = FindRegexVarEnd(PatternStr.substr(2), SM); 259061d2baaSEli Bendersky 2608879e06dSChris Lattner if (End == StringRef::npos) { 2618879e06dSChris Lattner SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 26203b80a40SChris Lattner SourceMgr::DK_Error, 26303b80a40SChris Lattner "invalid named regex reference, no ]] found"); 264f08d2db9SChris Lattner return true; 265f08d2db9SChris Lattner } 266f08d2db9SChris Lattner 267061d2baaSEli Bendersky StringRef MatchStr = PatternStr.substr(2, End); 268061d2baaSEli Bendersky PatternStr = PatternStr.substr(End+4); 2698879e06dSChris Lattner 2708879e06dSChris Lattner // Get the regex name (e.g. "foo"). 2718879e06dSChris Lattner size_t NameEnd = MatchStr.find(':'); 2728879e06dSChris Lattner StringRef Name = MatchStr.substr(0, NameEnd); 2738879e06dSChris Lattner 2748879e06dSChris Lattner if (Name.empty()) { 27503b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 27603b80a40SChris Lattner "invalid name in named regex: empty name"); 2778879e06dSChris Lattner return true; 2788879e06dSChris Lattner } 2798879e06dSChris Lattner 28092987fb3SAlexander Kornienko // Verify that the name/expression is well formed. FileCheck currently 28192987fb3SAlexander Kornienko // supports @LINE, @LINE+number, @LINE-number expressions. The check here 28292987fb3SAlexander Kornienko // is relaxed, more strict check is performed in \c EvaluateExpression. 28392987fb3SAlexander Kornienko bool IsExpression = false; 28492987fb3SAlexander Kornienko for (unsigned i = 0, e = Name.size(); i != e; ++i) { 28592987fb3SAlexander Kornienko if (i == 0 && Name[i] == '@') { 28692987fb3SAlexander Kornienko if (NameEnd != StringRef::npos) { 28792987fb3SAlexander Kornienko SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 28892987fb3SAlexander Kornienko SourceMgr::DK_Error, 28992987fb3SAlexander Kornienko "invalid name in named regex definition"); 29092987fb3SAlexander Kornienko return true; 29192987fb3SAlexander Kornienko } 29292987fb3SAlexander Kornienko IsExpression = true; 29392987fb3SAlexander Kornienko continue; 29492987fb3SAlexander Kornienko } 29592987fb3SAlexander Kornienko if (Name[i] != '_' && !isalnum(Name[i]) && 29692987fb3SAlexander Kornienko (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) { 2978879e06dSChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), 29803b80a40SChris Lattner SourceMgr::DK_Error, "invalid name in named regex"); 2998879e06dSChris Lattner return true; 3008879e06dSChris Lattner } 30192987fb3SAlexander Kornienko } 3028879e06dSChris Lattner 3038879e06dSChris Lattner // Name can't start with a digit. 30483c74e9fSGuy Benyei if (isdigit(static_cast<unsigned char>(Name[0]))) { 30503b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 30603b80a40SChris Lattner "invalid name in named regex"); 3078879e06dSChris Lattner return true; 3088879e06dSChris Lattner } 3098879e06dSChris Lattner 3108879e06dSChris Lattner // Handle [[foo]]. 3118879e06dSChris Lattner if (NameEnd == StringRef::npos) { 312e8b8f1bcSEli Bendersky // Handle variables that were defined earlier on the same line by 313e8b8f1bcSEli Bendersky // emitting a backreference. 314e8b8f1bcSEli Bendersky if (VariableDefs.find(Name) != VariableDefs.end()) { 315e8b8f1bcSEli Bendersky unsigned VarParenNum = VariableDefs[Name]; 316e8b8f1bcSEli Bendersky if (VarParenNum < 1 || VarParenNum > 9) { 317e8b8f1bcSEli Bendersky SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 318e8b8f1bcSEli Bendersky SourceMgr::DK_Error, 319e8b8f1bcSEli Bendersky "Can't back-reference more than 9 variables"); 320e8b8f1bcSEli Bendersky return true; 321e8b8f1bcSEli Bendersky } 322e8b8f1bcSEli Bendersky AddBackrefToRegEx(VarParenNum); 323e8b8f1bcSEli Bendersky } else { 3248879e06dSChris Lattner VariableUses.push_back(std::make_pair(Name, RegExStr.size())); 325e8b8f1bcSEli Bendersky } 3268879e06dSChris Lattner continue; 3278879e06dSChris Lattner } 3288879e06dSChris Lattner 3298879e06dSChris Lattner // Handle [[foo:.*]]. 330e8b8f1bcSEli Bendersky VariableDefs[Name] = CurParen; 3318879e06dSChris Lattner RegExStr += '('; 3328879e06dSChris Lattner ++CurParen; 3338879e06dSChris Lattner 3348879e06dSChris Lattner if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) 3358879e06dSChris Lattner return true; 3368879e06dSChris Lattner 3378879e06dSChris Lattner RegExStr += ')'; 3388879e06dSChris Lattner } 3398879e06dSChris Lattner 3408879e06dSChris Lattner // Handle fixed string matches. 3418879e06dSChris Lattner // Find the end, which is the start of the next regex. 3428879e06dSChris Lattner size_t FixedMatchEnd = PatternStr.find("{{"); 3438879e06dSChris Lattner FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); 3446f4f77b7SHans Wennborg RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd)); 3458879e06dSChris Lattner PatternStr = PatternStr.substr(FixedMatchEnd); 346f08d2db9SChris Lattner } 347f08d2db9SChris Lattner 34885913ccaSJames Y Knight if (MatchFullLinesHere) { 34985913ccaSJames Y Knight if (!NoCanonicalizeWhiteSpace) 35085913ccaSJames Y Knight RegExStr += " *"; 35185913ccaSJames Y Knight RegExStr += '$'; 35285913ccaSJames Y Knight } 35385913ccaSJames Y Knight 35474d50731SChris Lattner return false; 35574d50731SChris Lattner } 35674d50731SChris Lattner 357e8b8f1bcSEli Bendersky bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, 3588879e06dSChris Lattner SourceMgr &SM) { 359e8b8f1bcSEli Bendersky Regex R(RS); 3608879e06dSChris Lattner std::string Error; 3618879e06dSChris Lattner if (!R.isValid(Error)) { 362e8b8f1bcSEli Bendersky SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error, 36303b80a40SChris Lattner "invalid regex: " + Error); 3648879e06dSChris Lattner return true; 3658879e06dSChris Lattner } 3668879e06dSChris Lattner 367e8b8f1bcSEli Bendersky RegExStr += RS.str(); 3688879e06dSChris Lattner CurParen += R.getNumMatches(); 3698879e06dSChris Lattner return false; 3708879e06dSChris Lattner } 371b16ab0c4SChris Lattner 372e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) { 373e8b8f1bcSEli Bendersky assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number"); 374e8b8f1bcSEli Bendersky std::string Backref = std::string("\\") + 375e8b8f1bcSEli Bendersky std::string(1, '0' + BackrefNum); 376e8b8f1bcSEli Bendersky RegExStr += Backref; 377e8b8f1bcSEli Bendersky } 378e8b8f1bcSEli Bendersky 37992987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const { 38092987fb3SAlexander Kornienko // The only supported expression is @LINE([\+-]\d+)? 38192987fb3SAlexander Kornienko if (!Expr.startswith("@LINE")) 38292987fb3SAlexander Kornienko return false; 38392987fb3SAlexander Kornienko Expr = Expr.substr(StringRef("@LINE").size()); 38492987fb3SAlexander Kornienko int Offset = 0; 38592987fb3SAlexander Kornienko if (!Expr.empty()) { 38692987fb3SAlexander Kornienko if (Expr[0] == '+') 38792987fb3SAlexander Kornienko Expr = Expr.substr(1); 38892987fb3SAlexander Kornienko else if (Expr[0] != '-') 38992987fb3SAlexander Kornienko return false; 39092987fb3SAlexander Kornienko if (Expr.getAsInteger(10, Offset)) 39192987fb3SAlexander Kornienko return false; 39292987fb3SAlexander Kornienko } 39392987fb3SAlexander Kornienko Value = llvm::itostr(LineNumber + Offset); 39492987fb3SAlexander Kornienko return true; 39592987fb3SAlexander Kornienko } 39692987fb3SAlexander Kornienko 397f08d2db9SChris Lattner /// Match - Match the pattern string against the input buffer Buffer. This 398f08d2db9SChris Lattner /// returns the position that is matched or npos if there is no match. If 399f08d2db9SChris Lattner /// there is a match, the size of the matched string is returned in MatchLen. 4008879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, 4018879e06dSChris Lattner StringMap<StringRef> &VariableTable) const { 402eba55822SJakob Stoklund Olesen // If this is the EOF pattern, match it immediately. 40338820972SMatt Arsenault if (CheckTy == Check::CheckEOF) { 404eba55822SJakob Stoklund Olesen MatchLen = 0; 405eba55822SJakob Stoklund Olesen return Buffer.size(); 406eba55822SJakob Stoklund Olesen } 407eba55822SJakob Stoklund Olesen 408221460e0SChris Lattner // If this is a fixed string pattern, just match it now. 409221460e0SChris Lattner if (!FixedStr.empty()) { 410221460e0SChris Lattner MatchLen = FixedStr.size(); 411221460e0SChris Lattner return Buffer.find(FixedStr); 412221460e0SChris Lattner } 413221460e0SChris Lattner 414b16ab0c4SChris Lattner // Regex match. 4158879e06dSChris Lattner 4168879e06dSChris Lattner // If there are variable uses, we need to create a temporary string with the 4178879e06dSChris Lattner // actual value. 4188879e06dSChris Lattner StringRef RegExToMatch = RegExStr; 4198879e06dSChris Lattner std::string TmpStr; 4208879e06dSChris Lattner if (!VariableUses.empty()) { 4218879e06dSChris Lattner TmpStr = RegExStr; 4228879e06dSChris Lattner 4238879e06dSChris Lattner unsigned InsertOffset = 0; 4248f870499SBenjamin Kramer for (const auto &VariableUse : VariableUses) { 42592987fb3SAlexander Kornienko std::string Value; 42692987fb3SAlexander Kornienko 4278f870499SBenjamin Kramer if (VariableUse.first[0] == '@') { 4288f870499SBenjamin Kramer if (!EvaluateExpression(VariableUse.first, Value)) 42992987fb3SAlexander Kornienko return StringRef::npos; 43092987fb3SAlexander Kornienko } else { 431e0ef65abSDaniel Dunbar StringMap<StringRef>::iterator it = 4328f870499SBenjamin Kramer VariableTable.find(VariableUse.first); 433e0ef65abSDaniel Dunbar // If the variable is undefined, return an error. 434e0ef65abSDaniel Dunbar if (it == VariableTable.end()) 435e0ef65abSDaniel Dunbar return StringRef::npos; 436e0ef65abSDaniel Dunbar 4376f4f77b7SHans Wennborg // Look up the value and escape it so that we can put it into the regex. 4386f4f77b7SHans Wennborg Value += Regex::escape(it->second); 43992987fb3SAlexander Kornienko } 4408879e06dSChris Lattner 4418879e06dSChris Lattner // Plop it into the regex at the adjusted offset. 4428f870499SBenjamin Kramer TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset, 4438879e06dSChris Lattner Value.begin(), Value.end()); 4448879e06dSChris Lattner InsertOffset += Value.size(); 4458879e06dSChris Lattner } 4468879e06dSChris Lattner 4478879e06dSChris Lattner // Match the newly constructed regex. 4488879e06dSChris Lattner RegExToMatch = TmpStr; 4498879e06dSChris Lattner } 4508879e06dSChris Lattner 4518879e06dSChris Lattner 452b16ab0c4SChris Lattner SmallVector<StringRef, 4> MatchInfo; 4538879e06dSChris Lattner if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo)) 454f08d2db9SChris Lattner return StringRef::npos; 455b16ab0c4SChris Lattner 456b16ab0c4SChris Lattner // Successful regex match. 457b16ab0c4SChris Lattner assert(!MatchInfo.empty() && "Didn't get any match"); 458b16ab0c4SChris Lattner StringRef FullMatch = MatchInfo[0]; 459b16ab0c4SChris Lattner 4608879e06dSChris Lattner // If this defines any variables, remember their values. 4618f870499SBenjamin Kramer for (const auto &VariableDef : VariableDefs) { 4628f870499SBenjamin Kramer assert(VariableDef.second < MatchInfo.size() && "Internal paren error"); 4638f870499SBenjamin Kramer VariableTable[VariableDef.first] = MatchInfo[VariableDef.second]; 4640a4c44bdSChris Lattner } 4650a4c44bdSChris Lattner 466b16ab0c4SChris Lattner MatchLen = FullMatch.size(); 467b16ab0c4SChris Lattner return FullMatch.data()-Buffer.data(); 468f08d2db9SChris Lattner } 469f08d2db9SChris Lattner 470fd29d886SDaniel Dunbar unsigned Pattern::ComputeMatchDistance(StringRef Buffer, 471fd29d886SDaniel Dunbar const StringMap<StringRef> &VariableTable) const { 472fd29d886SDaniel Dunbar // Just compute the number of matching characters. For regular expressions, we 473fd29d886SDaniel Dunbar // just compare against the regex itself and hope for the best. 474fd29d886SDaniel Dunbar // 475fd29d886SDaniel Dunbar // FIXME: One easy improvement here is have the regex lib generate a single 476fd29d886SDaniel Dunbar // example regular expression which matches, and use that as the example 477fd29d886SDaniel Dunbar // string. 478fd29d886SDaniel Dunbar StringRef ExampleString(FixedStr); 479fd29d886SDaniel Dunbar if (ExampleString.empty()) 480fd29d886SDaniel Dunbar ExampleString = RegExStr; 481fd29d886SDaniel Dunbar 482e9aa36c8SDaniel Dunbar // Only compare up to the first line in the buffer, or the string size. 483e9aa36c8SDaniel Dunbar StringRef BufferPrefix = Buffer.substr(0, ExampleString.size()); 484e9aa36c8SDaniel Dunbar BufferPrefix = BufferPrefix.split('\n').first; 485e9aa36c8SDaniel Dunbar return BufferPrefix.edit_distance(ExampleString); 486fd29d886SDaniel Dunbar } 487fd29d886SDaniel Dunbar 488e0ef65abSDaniel Dunbar void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 489e0ef65abSDaniel Dunbar const StringMap<StringRef> &VariableTable) const{ 490e0ef65abSDaniel Dunbar // If this was a regular expression using variables, print the current 491e0ef65abSDaniel Dunbar // variable values. 492e0ef65abSDaniel Dunbar if (!VariableUses.empty()) { 4938f870499SBenjamin Kramer for (const auto &VariableUse : VariableUses) { 494e69170a1SAlp Toker SmallString<256> Msg; 495e69170a1SAlp Toker raw_svector_ostream OS(Msg); 4968f870499SBenjamin Kramer StringRef Var = VariableUse.first; 49792987fb3SAlexander Kornienko if (Var[0] == '@') { 49892987fb3SAlexander Kornienko std::string Value; 49992987fb3SAlexander Kornienko if (EvaluateExpression(Var, Value)) { 50092987fb3SAlexander Kornienko OS << "with expression \""; 50192987fb3SAlexander Kornienko OS.write_escaped(Var) << "\" equal to \""; 50292987fb3SAlexander Kornienko OS.write_escaped(Value) << "\""; 50392987fb3SAlexander Kornienko } else { 50492987fb3SAlexander Kornienko OS << "uses incorrect expression \""; 50592987fb3SAlexander Kornienko OS.write_escaped(Var) << "\""; 50692987fb3SAlexander Kornienko } 50792987fb3SAlexander Kornienko } else { 50892987fb3SAlexander Kornienko StringMap<StringRef>::const_iterator it = VariableTable.find(Var); 509e0ef65abSDaniel Dunbar 510e0ef65abSDaniel Dunbar // Check for undefined variable references. 511e0ef65abSDaniel Dunbar if (it == VariableTable.end()) { 512e0ef65abSDaniel Dunbar OS << "uses undefined variable \""; 51392987fb3SAlexander Kornienko OS.write_escaped(Var) << "\""; 514e0ef65abSDaniel Dunbar } else { 515e0ef65abSDaniel Dunbar OS << "with variable \""; 516e0ef65abSDaniel Dunbar OS.write_escaped(Var) << "\" equal to \""; 517e0ef65abSDaniel Dunbar OS.write_escaped(it->second) << "\""; 518e0ef65abSDaniel Dunbar } 51992987fb3SAlexander Kornienko } 520e0ef65abSDaniel Dunbar 52103b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 52203b80a40SChris Lattner OS.str()); 523e0ef65abSDaniel Dunbar } 524e0ef65abSDaniel Dunbar } 525fd29d886SDaniel Dunbar 526fd29d886SDaniel Dunbar // Attempt to find the closest/best fuzzy match. Usually an error happens 527fd29d886SDaniel Dunbar // because some string in the output didn't exactly match. In these cases, we 528fd29d886SDaniel Dunbar // would like to show the user a best guess at what "should have" matched, to 529fd29d886SDaniel Dunbar // save them having to actually check the input manually. 530fd29d886SDaniel Dunbar size_t NumLinesForward = 0; 531fd29d886SDaniel Dunbar size_t Best = StringRef::npos; 532fd29d886SDaniel Dunbar double BestQuality = 0; 533fd29d886SDaniel Dunbar 534fd29d886SDaniel Dunbar // Use an arbitrary 4k limit on how far we will search. 5352bf486ebSDan Gohman for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { 536fd29d886SDaniel Dunbar if (Buffer[i] == '\n') 537fd29d886SDaniel Dunbar ++NumLinesForward; 538fd29d886SDaniel Dunbar 539df22bbf7SDan Gohman // Patterns have leading whitespace stripped, so skip whitespace when 540df22bbf7SDan Gohman // looking for something which looks like a pattern. 541df22bbf7SDan Gohman if (Buffer[i] == ' ' || Buffer[i] == '\t') 542df22bbf7SDan Gohman continue; 543df22bbf7SDan Gohman 544fd29d886SDaniel Dunbar // Compute the "quality" of this match as an arbitrary combination of the 545fd29d886SDaniel Dunbar // match distance and the number of lines skipped to get to this match. 546fd29d886SDaniel Dunbar unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); 547fd29d886SDaniel Dunbar double Quality = Distance + (NumLinesForward / 100.); 548fd29d886SDaniel Dunbar 549fd29d886SDaniel Dunbar if (Quality < BestQuality || Best == StringRef::npos) { 550fd29d886SDaniel Dunbar Best = i; 551fd29d886SDaniel Dunbar BestQuality = Quality; 552fd29d886SDaniel Dunbar } 553fd29d886SDaniel Dunbar } 554fd29d886SDaniel Dunbar 555fd29d886SDaniel Dunbar // Print the "possible intended match here" line if we found something 556c069cc8eSDaniel Dunbar // reasonable and not equal to what we showed in the "scanning from here" 557c069cc8eSDaniel Dunbar // line. 558c069cc8eSDaniel Dunbar if (Best && Best != StringRef::npos && BestQuality < 50) { 559fd29d886SDaniel Dunbar SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), 56003b80a40SChris Lattner SourceMgr::DK_Note, "possible intended match here"); 561fd29d886SDaniel Dunbar 562fd29d886SDaniel Dunbar // FIXME: If we wanted to be really friendly we would show why the match 563fd29d886SDaniel Dunbar // failed, as it can be hard to spot simple one character differences. 564fd29d886SDaniel Dunbar } 565e0ef65abSDaniel Dunbar } 56674d50731SChris Lattner 56781e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { 568061d2baaSEli Bendersky // Offset keeps track of the current offset within the input Str 569061d2baaSEli Bendersky size_t Offset = 0; 570061d2baaSEli Bendersky // [...] Nesting depth 571061d2baaSEli Bendersky size_t BracketDepth = 0; 572061d2baaSEli Bendersky 573061d2baaSEli Bendersky while (!Str.empty()) { 574061d2baaSEli Bendersky if (Str.startswith("]]") && BracketDepth == 0) 575061d2baaSEli Bendersky return Offset; 576061d2baaSEli Bendersky if (Str[0] == '\\') { 577061d2baaSEli Bendersky // Backslash escapes the next char within regexes, so skip them both. 578061d2baaSEli Bendersky Str = Str.substr(2); 579061d2baaSEli Bendersky Offset += 2; 580061d2baaSEli Bendersky } else { 581061d2baaSEli Bendersky switch (Str[0]) { 582061d2baaSEli Bendersky default: 583061d2baaSEli Bendersky break; 584061d2baaSEli Bendersky case '[': 585061d2baaSEli Bendersky BracketDepth++; 586061d2baaSEli Bendersky break; 587061d2baaSEli Bendersky case ']': 58881e5cd9eSAdrian Prantl if (BracketDepth == 0) { 58981e5cd9eSAdrian Prantl SM.PrintMessage(SMLoc::getFromPointer(Str.data()), 59081e5cd9eSAdrian Prantl SourceMgr::DK_Error, 59181e5cd9eSAdrian Prantl "missing closing \"]\" for regex variable"); 59281e5cd9eSAdrian Prantl exit(1); 59381e5cd9eSAdrian Prantl } 594061d2baaSEli Bendersky BracketDepth--; 595061d2baaSEli Bendersky break; 596061d2baaSEli Bendersky } 597061d2baaSEli Bendersky Str = Str.substr(1); 598061d2baaSEli Bendersky Offset++; 599061d2baaSEli Bendersky } 600061d2baaSEli Bendersky } 601061d2baaSEli Bendersky 602061d2baaSEli Bendersky return StringRef::npos; 603061d2baaSEli Bendersky } 604061d2baaSEli Bendersky 605061d2baaSEli Bendersky 60674d50731SChris Lattner //===----------------------------------------------------------------------===// 60774d50731SChris Lattner // Check Strings. 60874d50731SChris Lattner //===----------------------------------------------------------------------===// 6093b40b445SChris Lattner 6103b40b445SChris Lattner /// CheckString - This is a check that we found in the input file. 6113b40b445SChris Lattner struct CheckString { 6123b40b445SChris Lattner /// Pat - The pattern to match. 6133b40b445SChris Lattner Pattern Pat; 61426cccfe1SChris Lattner 61513df4626SMatt Arsenault /// Prefix - Which prefix name this check matched. 61613df4626SMatt Arsenault StringRef Prefix; 61713df4626SMatt Arsenault 61826cccfe1SChris Lattner /// Loc - The location in the match file that the check string was specified. 61926cccfe1SChris Lattner SMLoc Loc; 62026cccfe1SChris Lattner 62138820972SMatt Arsenault /// CheckTy - Specify what kind of check this is. e.g. CHECK-NEXT: directive, 62238820972SMatt Arsenault /// as opposed to a CHECK: directive. 62385913ccaSJames Y Knight // Check::CheckType CheckTy; 624f8bd2e5bSStephen Lin 62591a1b2c9SMichael Liao /// DagNotStrings - These are all of the strings that are disallowed from 626236d2d5eSChris Lattner /// occurring between this match string and the previous one (or start of 627236d2d5eSChris Lattner /// file). 62891a1b2c9SMichael Liao std::vector<Pattern> DagNotStrings; 629236d2d5eSChris Lattner 63085913ccaSJames Y Knight CheckString(const Pattern &P, StringRef S, SMLoc L) 63185913ccaSJames Y Knight : Pat(P), Prefix(S), Loc(L) {} 632dcc7d48dSMichael Liao 63391a1b2c9SMichael Liao /// Check - Match check string and its "not strings" and/or "dag strings". 634e93a3a08SStephen Lin size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, 635f8bd2e5bSStephen Lin size_t &MatchLen, StringMap<StringRef> &VariableTable) const; 636dcc7d48dSMichael Liao 637dcc7d48dSMichael Liao /// CheckNext - Verify there is a single line in the given buffer. 638dcc7d48dSMichael Liao bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; 639dcc7d48dSMichael Liao 64001ac1707SDuncan P. N. Exon Smith /// CheckSame - Verify there is no newline in the given buffer. 64101ac1707SDuncan P. N. Exon Smith bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; 64201ac1707SDuncan P. N. Exon Smith 643dcc7d48dSMichael Liao /// CheckNot - Verify there's no "not strings" in the given buffer. 644dcc7d48dSMichael Liao bool CheckNot(const SourceMgr &SM, StringRef Buffer, 64591a1b2c9SMichael Liao const std::vector<const Pattern *> &NotStrings, 64691a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) const; 64791a1b2c9SMichael Liao 64891a1b2c9SMichael Liao /// CheckDag - Match "dag strings" and their mixed "not strings". 64991a1b2c9SMichael Liao size_t CheckDag(const SourceMgr &SM, StringRef Buffer, 65091a1b2c9SMichael Liao std::vector<const Pattern *> &NotStrings, 651dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const; 65226cccfe1SChris Lattner }; 65326cccfe1SChris Lattner 6545ea04c38SGuy Benyei /// Canonicalize whitespaces in the input file. Line endings are replaced 6555ea04c38SGuy Benyei /// with UNIX-style '\n'. 6565ea04c38SGuy Benyei /// 6575ea04c38SGuy Benyei /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace 6585ea04c38SGuy Benyei /// characters to a single space. 6591961f14cSDavid Blaikie static std::unique_ptr<MemoryBuffer> 6601961f14cSDavid Blaikie CanonicalizeInputFile(std::unique_ptr<MemoryBuffer> MB, 6615ea04c38SGuy Benyei bool PreserveHorizontal) { 6620e45d24aSChris Lattner SmallString<128> NewFile; 663a2f8fc5aSChris Lattner NewFile.reserve(MB->getBufferSize()); 664a2f8fc5aSChris Lattner 665a2f8fc5aSChris Lattner for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd(); 666a2f8fc5aSChris Lattner Ptr != End; ++Ptr) { 667fd781bf0SNAKAMURA Takumi // Eliminate trailing dosish \r. 668fd781bf0SNAKAMURA Takumi if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { 669fd781bf0SNAKAMURA Takumi continue; 670fd781bf0SNAKAMURA Takumi } 671fd781bf0SNAKAMURA Takumi 6725ea04c38SGuy Benyei // If current char is not a horizontal whitespace or if horizontal 6735ea04c38SGuy Benyei // whitespace canonicalization is disabled, dump it to output as is. 6745ea04c38SGuy Benyei if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) { 675a2f8fc5aSChris Lattner NewFile.push_back(*Ptr); 676a2f8fc5aSChris Lattner continue; 677a2f8fc5aSChris Lattner } 678a2f8fc5aSChris Lattner 679a2f8fc5aSChris Lattner // Otherwise, add one space and advance over neighboring space. 680a2f8fc5aSChris Lattner NewFile.push_back(' '); 681a2f8fc5aSChris Lattner while (Ptr+1 != End && 682a2f8fc5aSChris Lattner (Ptr[1] == ' ' || Ptr[1] == '\t')) 683a2f8fc5aSChris Lattner ++Ptr; 684a2f8fc5aSChris Lattner } 685a2f8fc5aSChris Lattner 6861961f14cSDavid Blaikie return std::unique_ptr<MemoryBuffer>( 6871961f14cSDavid Blaikie MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier())); 688a2f8fc5aSChris Lattner } 689a2f8fc5aSChris Lattner 69038820972SMatt Arsenault static bool IsPartOfWord(char c) { 69138820972SMatt Arsenault return (isalnum(c) || c == '-' || c == '_'); 69238820972SMatt Arsenault } 69338820972SMatt Arsenault 69413df4626SMatt Arsenault // Get the size of the prefix extension. 69513df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) { 69613df4626SMatt Arsenault switch (Ty) { 69713df4626SMatt Arsenault case Check::CheckNone: 698*a908e7bdSPaul Robinson case Check::CheckBadNot: 69913df4626SMatt Arsenault return 0; 70013df4626SMatt Arsenault 70113df4626SMatt Arsenault case Check::CheckPlain: 70213df4626SMatt Arsenault return sizeof(":") - 1; 70313df4626SMatt Arsenault 70413df4626SMatt Arsenault case Check::CheckNext: 70513df4626SMatt Arsenault return sizeof("-NEXT:") - 1; 70613df4626SMatt Arsenault 70701ac1707SDuncan P. N. Exon Smith case Check::CheckSame: 70801ac1707SDuncan P. N. Exon Smith return sizeof("-SAME:") - 1; 70901ac1707SDuncan P. N. Exon Smith 71013df4626SMatt Arsenault case Check::CheckNot: 71113df4626SMatt Arsenault return sizeof("-NOT:") - 1; 71213df4626SMatt Arsenault 71313df4626SMatt Arsenault case Check::CheckDAG: 71413df4626SMatt Arsenault return sizeof("-DAG:") - 1; 71513df4626SMatt Arsenault 71613df4626SMatt Arsenault case Check::CheckLabel: 71713df4626SMatt Arsenault return sizeof("-LABEL:") - 1; 71813df4626SMatt Arsenault 71913df4626SMatt Arsenault case Check::CheckEOF: 72013df4626SMatt Arsenault llvm_unreachable("Should not be using EOF size"); 72113df4626SMatt Arsenault } 72213df4626SMatt Arsenault 72313df4626SMatt Arsenault llvm_unreachable("Bad check type"); 72413df4626SMatt Arsenault } 72513df4626SMatt Arsenault 72613df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) { 727c4d2d471SMatt Arsenault char NextChar = Buffer[Prefix.size()]; 72838820972SMatt Arsenault 72938820972SMatt Arsenault // Verify that the : is present after the prefix. 73013df4626SMatt Arsenault if (NextChar == ':') 73138820972SMatt Arsenault return Check::CheckPlain; 73238820972SMatt Arsenault 73313df4626SMatt Arsenault if (NextChar != '-') 73438820972SMatt Arsenault return Check::CheckNone; 73538820972SMatt Arsenault 736c4d2d471SMatt Arsenault StringRef Rest = Buffer.drop_front(Prefix.size() + 1); 73713df4626SMatt Arsenault if (Rest.startswith("NEXT:")) 73838820972SMatt Arsenault return Check::CheckNext; 73938820972SMatt Arsenault 74001ac1707SDuncan P. N. Exon Smith if (Rest.startswith("SAME:")) 74101ac1707SDuncan P. N. Exon Smith return Check::CheckSame; 74201ac1707SDuncan P. N. Exon Smith 74313df4626SMatt Arsenault if (Rest.startswith("NOT:")) 74438820972SMatt Arsenault return Check::CheckNot; 74538820972SMatt Arsenault 74613df4626SMatt Arsenault if (Rest.startswith("DAG:")) 74738820972SMatt Arsenault return Check::CheckDAG; 74838820972SMatt Arsenault 74913df4626SMatt Arsenault if (Rest.startswith("LABEL:")) 75038820972SMatt Arsenault return Check::CheckLabel; 75113df4626SMatt Arsenault 752*a908e7bdSPaul Robinson // You can't combine -NOT with another suffix. 753*a908e7bdSPaul Robinson if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") || 754*a908e7bdSPaul Robinson Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") || 755*a908e7bdSPaul Robinson Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:")) 756*a908e7bdSPaul Robinson return Check::CheckBadNot; 757*a908e7bdSPaul Robinson 75813df4626SMatt Arsenault return Check::CheckNone; 75938820972SMatt Arsenault } 76038820972SMatt Arsenault 76113df4626SMatt Arsenault // From the given position, find the next character after the word. 76213df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) { 76313df4626SMatt Arsenault while (Loc < Str.size() && IsPartOfWord(Str[Loc])) 76413df4626SMatt Arsenault ++Loc; 76513df4626SMatt Arsenault return Loc; 76613df4626SMatt Arsenault } 76713df4626SMatt Arsenault 76813df4626SMatt Arsenault // Try to find the first match in buffer for any prefix. If a valid match is 76913df4626SMatt Arsenault // found, return that prefix and set its type and location. If there are almost 77013df4626SMatt Arsenault // matches (e.g. the actual prefix string is found, but is not an actual check 77113df4626SMatt Arsenault // string), but no valid match, return an empty string and set the position to 77213df4626SMatt Arsenault // resume searching from. If no partial matches are found, return an empty 77313df4626SMatt Arsenault // string and the location will be StringRef::npos. If one prefix is a substring 77413df4626SMatt Arsenault // of another, the maximal match should be found. e.g. if "A" and "AA" are 77513df4626SMatt Arsenault // prefixes then AA-CHECK: should match the second one. 77613df4626SMatt Arsenault static StringRef FindFirstCandidateMatch(StringRef &Buffer, 77713df4626SMatt Arsenault Check::CheckType &CheckTy, 77813df4626SMatt Arsenault size_t &CheckLoc) { 77913df4626SMatt Arsenault StringRef FirstPrefix; 78013df4626SMatt Arsenault size_t FirstLoc = StringRef::npos; 78113df4626SMatt Arsenault size_t SearchLoc = StringRef::npos; 78213df4626SMatt Arsenault Check::CheckType FirstTy = Check::CheckNone; 78313df4626SMatt Arsenault 78413df4626SMatt Arsenault CheckTy = Check::CheckNone; 78513df4626SMatt Arsenault CheckLoc = StringRef::npos; 78613df4626SMatt Arsenault 7878f870499SBenjamin Kramer for (StringRef Prefix : CheckPrefixes) { 78813df4626SMatt Arsenault size_t PrefixLoc = Buffer.find(Prefix); 78913df4626SMatt Arsenault 79013df4626SMatt Arsenault if (PrefixLoc == StringRef::npos) 79113df4626SMatt Arsenault continue; 79213df4626SMatt Arsenault 79313df4626SMatt Arsenault // Track where we are searching for invalid prefixes that look almost right. 79413df4626SMatt Arsenault // We need to only advance to the first partial match on the next attempt 79513df4626SMatt Arsenault // since a partial match could be a substring of a later, valid prefix. 79613df4626SMatt Arsenault // Need to skip to the end of the word, otherwise we could end up 79713df4626SMatt Arsenault // matching a prefix in a substring later. 79813df4626SMatt Arsenault if (PrefixLoc < SearchLoc) 79913df4626SMatt Arsenault SearchLoc = SkipWord(Buffer, PrefixLoc); 80013df4626SMatt Arsenault 80113df4626SMatt Arsenault // We only want to find the first match to avoid skipping some. 80213df4626SMatt Arsenault if (PrefixLoc > FirstLoc) 80313df4626SMatt Arsenault continue; 804a7181a1bSAlexey Samsonov // If one matching check-prefix is a prefix of another, choose the 805a7181a1bSAlexey Samsonov // longer one. 806a7181a1bSAlexey Samsonov if (PrefixLoc == FirstLoc && Prefix.size() < FirstPrefix.size()) 807a7181a1bSAlexey Samsonov continue; 80813df4626SMatt Arsenault 80913df4626SMatt Arsenault StringRef Rest = Buffer.drop_front(PrefixLoc); 81013df4626SMatt Arsenault // Make sure we have actually found the prefix, and not a word containing 81113df4626SMatt Arsenault // it. This should also prevent matching the wrong prefix when one is a 81213df4626SMatt Arsenault // substring of another. 81313df4626SMatt Arsenault if (PrefixLoc != 0 && IsPartOfWord(Buffer[PrefixLoc - 1])) 81443b5f572SDaniel Sanders FirstTy = Check::CheckNone; 81543b5f572SDaniel Sanders else 81643b5f572SDaniel Sanders FirstTy = FindCheckType(Rest, Prefix); 81713df4626SMatt Arsenault 81813df4626SMatt Arsenault FirstLoc = PrefixLoc; 819a7181a1bSAlexey Samsonov FirstPrefix = Prefix; 82013df4626SMatt Arsenault } 82113df4626SMatt Arsenault 822a7181a1bSAlexey Samsonov // If the first prefix is invalid, we should continue the search after it. 823a7181a1bSAlexey Samsonov if (FirstTy == Check::CheckNone) { 82413df4626SMatt Arsenault CheckLoc = SearchLoc; 825a7181a1bSAlexey Samsonov return ""; 826a7181a1bSAlexey Samsonov } 827a7181a1bSAlexey Samsonov 82813df4626SMatt Arsenault CheckTy = FirstTy; 82913df4626SMatt Arsenault CheckLoc = FirstLoc; 83013df4626SMatt Arsenault return FirstPrefix; 83113df4626SMatt Arsenault } 83213df4626SMatt Arsenault 83313df4626SMatt Arsenault static StringRef FindFirstMatchingPrefix(StringRef &Buffer, 83413df4626SMatt Arsenault unsigned &LineNumber, 83513df4626SMatt Arsenault Check::CheckType &CheckTy, 83613df4626SMatt Arsenault size_t &CheckLoc) { 83713df4626SMatt Arsenault while (!Buffer.empty()) { 83813df4626SMatt Arsenault StringRef Prefix = FindFirstCandidateMatch(Buffer, CheckTy, CheckLoc); 83913df4626SMatt Arsenault // If we found a real match, we are done. 84013df4626SMatt Arsenault if (!Prefix.empty()) { 84113df4626SMatt Arsenault LineNumber += Buffer.substr(0, CheckLoc).count('\n'); 84213df4626SMatt Arsenault return Prefix; 84313df4626SMatt Arsenault } 84413df4626SMatt Arsenault 84513df4626SMatt Arsenault // We didn't find any almost matches either, we are also done. 84613df4626SMatt Arsenault if (CheckLoc == StringRef::npos) 84713df4626SMatt Arsenault return StringRef(); 84813df4626SMatt Arsenault 84913df4626SMatt Arsenault LineNumber += Buffer.substr(0, CheckLoc + 1).count('\n'); 85013df4626SMatt Arsenault 85113df4626SMatt Arsenault // Advance to the last possible match we found and try again. 85213df4626SMatt Arsenault Buffer = Buffer.drop_front(CheckLoc + 1); 85313df4626SMatt Arsenault } 85413df4626SMatt Arsenault 85513df4626SMatt Arsenault return StringRef(); 85638820972SMatt Arsenault } 857ee3c74fbSChris Lattner 858ee3c74fbSChris Lattner /// ReadCheckFile - Read the check file, which specifies the sequence of 859ee3c74fbSChris Lattner /// expected strings. The strings are added to the CheckStrings vector. 86043d50d4aSEli Bendersky /// Returns true in case of an error, false otherwise. 861ee3c74fbSChris Lattner static bool ReadCheckFile(SourceMgr &SM, 86226cccfe1SChris Lattner std::vector<CheckString> &CheckStrings) { 863adf21f2aSRafael Espindola ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 864adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(CheckFilename); 865adf21f2aSRafael Espindola if (std::error_code EC = FileOrErr.getError()) { 866adf21f2aSRafael Espindola errs() << "Could not open check file '" << CheckFilename 867adf21f2aSRafael Espindola << "': " << EC.message() << '\n'; 868ee3c74fbSChris Lattner return true; 869ee3c74fbSChris Lattner } 870a2f8fc5aSChris Lattner 871a2f8fc5aSChris Lattner // If we want to canonicalize whitespace, strip excess whitespace from the 8725ea04c38SGuy Benyei // buffer containing the CHECK lines. Remove DOS style line endings. 8733560ff2cSRafael Espindola std::unique_ptr<MemoryBuffer> F = CanonicalizeInputFile( 8743560ff2cSRafael Espindola std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace); 875ee3c74fbSChris Lattner 87610f10cedSChris Lattner // Find all instances of CheckPrefix followed by : in the file. 877caa5fc0cSChris Lattner StringRef Buffer = F->getBuffer(); 87856ccdbbdSAlexander Kornienko 8791961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(F), SMLoc()); 8801961f14cSDavid Blaikie 88156ccdbbdSAlexander Kornienko std::vector<Pattern> ImplicitNegativeChecks; 88256ccdbbdSAlexander Kornienko for (const auto &PatternString : ImplicitCheckNot) { 88356ccdbbdSAlexander Kornienko // Create a buffer with fake command line content in order to display the 88456ccdbbdSAlexander Kornienko // command line option responsible for the specific implicit CHECK-NOT. 885ff43d69dSDavid Blaikie std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str(); 88656ccdbbdSAlexander Kornienko std::string Suffix = "'"; 8873560ff2cSRafael Espindola std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy( 8883560ff2cSRafael Espindola Prefix + PatternString + Suffix, "command line"); 8893560ff2cSRafael Espindola 89056ccdbbdSAlexander Kornienko StringRef PatternInBuffer = 89156ccdbbdSAlexander Kornienko CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); 8921961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); 89356ccdbbdSAlexander Kornienko 89456ccdbbdSAlexander Kornienko ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); 89556ccdbbdSAlexander Kornienko ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, 89656ccdbbdSAlexander Kornienko "IMPLICIT-CHECK", SM, 0); 89756ccdbbdSAlexander Kornienko } 89856ccdbbdSAlexander Kornienko 89956ccdbbdSAlexander Kornienko 90056ccdbbdSAlexander Kornienko std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks; 901236d2d5eSChris Lattner 90243d50d4aSEli Bendersky // LineNumber keeps track of the line on which CheckPrefix instances are 90343d50d4aSEli Bendersky // found. 90492987fb3SAlexander Kornienko unsigned LineNumber = 1; 90592987fb3SAlexander Kornienko 906ee3c74fbSChris Lattner while (1) { 90713df4626SMatt Arsenault Check::CheckType CheckTy; 90813df4626SMatt Arsenault size_t PrefixLoc; 90913df4626SMatt Arsenault 91013df4626SMatt Arsenault // See if a prefix occurs in the memory buffer. 91113df4626SMatt Arsenault StringRef UsedPrefix = FindFirstMatchingPrefix(Buffer, 91213df4626SMatt Arsenault LineNumber, 91313df4626SMatt Arsenault CheckTy, 91413df4626SMatt Arsenault PrefixLoc); 91513df4626SMatt Arsenault if (UsedPrefix.empty()) 916ee3c74fbSChris Lattner break; 917ee3c74fbSChris Lattner 91813df4626SMatt Arsenault Buffer = Buffer.drop_front(PrefixLoc); 91992987fb3SAlexander Kornienko 92013df4626SMatt Arsenault // Location to use for error messages. 92113df4626SMatt Arsenault const char *UsedPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1); 92292987fb3SAlexander Kornienko 92313df4626SMatt Arsenault // PrefixLoc is to the start of the prefix. Skip to the end. 92413df4626SMatt Arsenault Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy)); 92510f10cedSChris Lattner 926*a908e7bdSPaul Robinson // Complain about useful-looking but unsupported suffixes. 927*a908e7bdSPaul Robinson if (CheckTy == Check::CheckBadNot) { 928*a908e7bdSPaul Robinson SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), 929*a908e7bdSPaul Robinson SourceMgr::DK_Error, 930*a908e7bdSPaul Robinson "unsupported -NOT combo on prefix '" + UsedPrefix + "'"); 931*a908e7bdSPaul Robinson return true; 932*a908e7bdSPaul Robinson } 933*a908e7bdSPaul Robinson 93438820972SMatt Arsenault // Okay, we found the prefix, yay. Remember the rest of the line, but ignore 93538820972SMatt Arsenault // leading and trailing whitespace. 936236d2d5eSChris Lattner Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); 937ee3c74fbSChris Lattner 938ee3c74fbSChris Lattner // Scan ahead to the end of line. 939caa5fc0cSChris Lattner size_t EOL = Buffer.find_first_of("\n\r"); 940ee3c74fbSChris Lattner 941838fb09aSDan Gohman // Remember the location of the start of the pattern, for diagnostics. 942838fb09aSDan Gohman SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); 943838fb09aSDan Gohman 94474d50731SChris Lattner // Parse the pattern. 94538820972SMatt Arsenault Pattern P(CheckTy); 94613df4626SMatt Arsenault if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber)) 947ee3c74fbSChris Lattner return true; 948ee3c74fbSChris Lattner 949f8bd2e5bSStephen Lin // Verify that CHECK-LABEL lines do not define or use variables 95038820972SMatt Arsenault if ((CheckTy == Check::CheckLabel) && P.hasVariable()) { 95113df4626SMatt Arsenault SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 952f8bd2e5bSStephen Lin SourceMgr::DK_Error, 95313df4626SMatt Arsenault "found '" + UsedPrefix + "-LABEL:'" 95413df4626SMatt Arsenault " with variable definition or use"); 955f8bd2e5bSStephen Lin return true; 956f8bd2e5bSStephen Lin } 957f8bd2e5bSStephen Lin 958236d2d5eSChris Lattner Buffer = Buffer.substr(EOL); 95974d50731SChris Lattner 960da108b4eSChris Lattner // Verify that CHECK-NEXT lines have at least one CHECK line before them. 96101ac1707SDuncan P. N. Exon Smith if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) && 96201ac1707SDuncan P. N. Exon Smith CheckStrings.empty()) { 96301ac1707SDuncan P. N. Exon Smith StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME"; 96413df4626SMatt Arsenault SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 96503b80a40SChris Lattner SourceMgr::DK_Error, 96601ac1707SDuncan P. N. Exon Smith "found '" + UsedPrefix + "-" + Type + "' without previous '" 96713df4626SMatt Arsenault + UsedPrefix + ": line"); 968da108b4eSChris Lattner return true; 969da108b4eSChris Lattner } 970da108b4eSChris Lattner 97191a1b2c9SMichael Liao // Handle CHECK-DAG/-NOT. 97238820972SMatt Arsenault if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) { 97391a1b2c9SMichael Liao DagNotMatches.push_back(P); 97474d50731SChris Lattner continue; 97574d50731SChris Lattner } 97674d50731SChris Lattner 977ee3c74fbSChris Lattner // Okay, add the string we captured to the output vector and move on. 97885913ccaSJames Y Knight CheckStrings.emplace_back(P, UsedPrefix, PatternLoc); 97991a1b2c9SMichael Liao std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 98056ccdbbdSAlexander Kornienko DagNotMatches = ImplicitNegativeChecks; 981ee3c74fbSChris Lattner } 982ee3c74fbSChris Lattner 98313df4626SMatt Arsenault // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first 98413df4626SMatt Arsenault // prefix as a filler for the error message. 98591a1b2c9SMichael Liao if (!DagNotMatches.empty()) { 986f5e2fc47SBenjamin Kramer CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(), 98785913ccaSJames Y Knight SMLoc::getFromPointer(Buffer.data())); 98891a1b2c9SMichael Liao std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 989eba55822SJakob Stoklund Olesen } 990eba55822SJakob Stoklund Olesen 991ee3c74fbSChris Lattner if (CheckStrings.empty()) { 99213df4626SMatt Arsenault errs() << "error: no check strings found with prefix" 99313df4626SMatt Arsenault << (CheckPrefixes.size() > 1 ? "es " : " "); 9943e3ef2f2SChris Bieneman prefix_iterator I = CheckPrefixes.begin(); 9953e3ef2f2SChris Bieneman prefix_iterator E = CheckPrefixes.end(); 9963e3ef2f2SChris Bieneman if (I != E) { 9973e3ef2f2SChris Bieneman errs() << "\'" << *I << ":'"; 9983e3ef2f2SChris Bieneman ++I; 99913df4626SMatt Arsenault } 10003e3ef2f2SChris Bieneman for (; I != E; ++I) 10013e3ef2f2SChris Bieneman errs() << ", \'" << *I << ":'"; 100213df4626SMatt Arsenault 100313df4626SMatt Arsenault errs() << '\n'; 1004ee3c74fbSChris Lattner return true; 1005ee3c74fbSChris Lattner } 1006ee3c74fbSChris Lattner 1007ee3c74fbSChris Lattner return false; 1008ee3c74fbSChris Lattner } 1009ee3c74fbSChris Lattner 10103c76c523SCraig Topper static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, 101191a1b2c9SMichael Liao const Pattern &Pat, StringRef Buffer, 1012e0ef65abSDaniel Dunbar StringMap<StringRef> &VariableTable) { 1013da108b4eSChris Lattner // Otherwise, we have an error, emit an error message. 101491a1b2c9SMichael Liao SM.PrintMessage(Loc, SourceMgr::DK_Error, 101503b80a40SChris Lattner "expected string not found in input"); 1016da108b4eSChris Lattner 1017da108b4eSChris Lattner // Print the "scanning from here" line. If the current position is at the 1018da108b4eSChris Lattner // end of a line, advance to the start of the next line. 1019caa5fc0cSChris Lattner Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r")); 1020da108b4eSChris Lattner 102103b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 102203b80a40SChris Lattner "scanning from here"); 1023e0ef65abSDaniel Dunbar 1024e0ef65abSDaniel Dunbar // Allow the pattern to print additional information if desired. 102591a1b2c9SMichael Liao Pat.PrintFailureInfo(SM, Buffer, VariableTable); 102691a1b2c9SMichael Liao } 102791a1b2c9SMichael Liao 102891a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, 102991a1b2c9SMichael Liao StringRef Buffer, 103091a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) { 103191a1b2c9SMichael Liao PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable); 1032da108b4eSChris Lattner } 1033da108b4eSChris Lattner 103437183584SChris Lattner /// CountNumNewlinesBetween - Count the number of newlines in the specified 103537183584SChris Lattner /// range. 1036592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range, 1037592fe880SRichard Smith const char *&FirstNewLine) { 1038da108b4eSChris Lattner unsigned NumNewLines = 0; 103937183584SChris Lattner while (1) { 1040da108b4eSChris Lattner // Scan for newline. 104137183584SChris Lattner Range = Range.substr(Range.find_first_of("\n\r")); 104237183584SChris Lattner if (Range.empty()) return NumNewLines; 1043da108b4eSChris Lattner 1044da108b4eSChris Lattner ++NumNewLines; 1045da108b4eSChris Lattner 1046da108b4eSChris Lattner // Handle \n\r and \r\n as a single newline. 104737183584SChris Lattner if (Range.size() > 1 && 104837183584SChris Lattner (Range[1] == '\n' || Range[1] == '\r') && 104937183584SChris Lattner (Range[0] != Range[1])) 105037183584SChris Lattner Range = Range.substr(1); 105137183584SChris Lattner Range = Range.substr(1); 1052592fe880SRichard Smith 1053592fe880SRichard Smith if (NumNewLines == 1) 1054592fe880SRichard Smith FirstNewLine = Range.begin(); 1055da108b4eSChris Lattner } 1056da108b4eSChris Lattner } 1057da108b4eSChris Lattner 1058dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, 1059e93a3a08SStephen Lin bool IsLabelScanMode, size_t &MatchLen, 1060dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const { 106191a1b2c9SMichael Liao size_t LastPos = 0; 106291a1b2c9SMichael Liao std::vector<const Pattern *> NotStrings; 106391a1b2c9SMichael Liao 1064e93a3a08SStephen Lin // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL 1065e93a3a08SStephen Lin // bounds; we have not processed variable definitions within the bounded block 1066e93a3a08SStephen Lin // yet so cannot handle any final CHECK-DAG yet; this is handled when going 1067e93a3a08SStephen Lin // over the block again (including the last CHECK-LABEL) in normal mode. 1068e93a3a08SStephen Lin if (!IsLabelScanMode) { 106991a1b2c9SMichael Liao // Match "dag strings" (with mixed "not strings" if any). 107091a1b2c9SMichael Liao LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable); 107191a1b2c9SMichael Liao if (LastPos == StringRef::npos) 107291a1b2c9SMichael Liao return StringRef::npos; 1073e93a3a08SStephen Lin } 107491a1b2c9SMichael Liao 107591a1b2c9SMichael Liao // Match itself from the last position after matching CHECK-DAG. 107691a1b2c9SMichael Liao StringRef MatchBuffer = Buffer.substr(LastPos); 107791a1b2c9SMichael Liao size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); 1078dcc7d48dSMichael Liao if (MatchPos == StringRef::npos) { 107991a1b2c9SMichael Liao PrintCheckFailed(SM, *this, MatchBuffer, VariableTable); 1080dcc7d48dSMichael Liao return StringRef::npos; 1081dcc7d48dSMichael Liao } 1082dcc7d48dSMichael Liao 1083e93a3a08SStephen Lin // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT 1084e93a3a08SStephen Lin // or CHECK-NOT 1085e93a3a08SStephen Lin if (!IsLabelScanMode) { 108691a1b2c9SMichael Liao StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 1087dcc7d48dSMichael Liao 1088dcc7d48dSMichael Liao // If this check is a "CHECK-NEXT", verify that the previous match was on 1089dcc7d48dSMichael Liao // the previous line (i.e. that there is one newline between them). 1090dcc7d48dSMichael Liao if (CheckNext(SM, SkippedRegion)) 1091dcc7d48dSMichael Liao return StringRef::npos; 1092dcc7d48dSMichael Liao 109301ac1707SDuncan P. N. Exon Smith // If this check is a "CHECK-SAME", verify that the previous match was on 109401ac1707SDuncan P. N. Exon Smith // the same line (i.e. that there is no newline between them). 109501ac1707SDuncan P. N. Exon Smith if (CheckSame(SM, SkippedRegion)) 109601ac1707SDuncan P. N. Exon Smith return StringRef::npos; 109701ac1707SDuncan P. N. Exon Smith 1098dcc7d48dSMichael Liao // If this match had "not strings", verify that they don't exist in the 1099dcc7d48dSMichael Liao // skipped region. 110091a1b2c9SMichael Liao if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) 1101dcc7d48dSMichael Liao return StringRef::npos; 1102f8bd2e5bSStephen Lin } 1103dcc7d48dSMichael Liao 11047dfb92b9SMehdi Amini return LastPos + MatchPos; 1105dcc7d48dSMichael Liao } 1106dcc7d48dSMichael Liao 1107dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { 110885913ccaSJames Y Knight if (Pat.getCheckTy() != Check::CheckNext) 1109dcc7d48dSMichael Liao return false; 1110dcc7d48dSMichael Liao 1111dcc7d48dSMichael Liao // Count the number of newlines between the previous match and this one. 1112dcc7d48dSMichael Liao assert(Buffer.data() != 1113dcc7d48dSMichael Liao SM.getMemoryBuffer( 1114dcc7d48dSMichael Liao SM.FindBufferContainingLoc( 1115dcc7d48dSMichael Liao SMLoc::getFromPointer(Buffer.data())))->getBufferStart() && 1116dcc7d48dSMichael Liao "CHECK-NEXT can't be the first check in a file"); 1117dcc7d48dSMichael Liao 111866f09ad0SCraig Topper const char *FirstNewLine = nullptr; 1119592fe880SRichard Smith unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 1120dcc7d48dSMichael Liao 1121dcc7d48dSMichael Liao if (NumNewLines == 0) { 112213df4626SMatt Arsenault SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + 1123dcc7d48dSMichael Liao "-NEXT: is on the same line as previous match"); 1124dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), 1125dcc7d48dSMichael Liao SourceMgr::DK_Note, "'next' match was here"); 1126dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1127dcc7d48dSMichael Liao "previous match ended here"); 1128dcc7d48dSMichael Liao return true; 1129dcc7d48dSMichael Liao } 1130dcc7d48dSMichael Liao 1131dcc7d48dSMichael Liao if (NumNewLines != 1) { 113213df4626SMatt Arsenault SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + 1133dcc7d48dSMichael Liao "-NEXT: is not on the line after the previous match"); 1134dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), 1135dcc7d48dSMichael Liao SourceMgr::DK_Note, "'next' match was here"); 1136dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1137dcc7d48dSMichael Liao "previous match ended here"); 1138592fe880SRichard Smith SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, 1139592fe880SRichard Smith "non-matching line after previous match is here"); 1140dcc7d48dSMichael Liao return true; 1141dcc7d48dSMichael Liao } 1142dcc7d48dSMichael Liao 1143dcc7d48dSMichael Liao return false; 1144dcc7d48dSMichael Liao } 1145dcc7d48dSMichael Liao 114601ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { 114785913ccaSJames Y Knight if (Pat.getCheckTy() != Check::CheckSame) 114801ac1707SDuncan P. N. Exon Smith return false; 114901ac1707SDuncan P. N. Exon Smith 115001ac1707SDuncan P. N. Exon Smith // Count the number of newlines between the previous match and this one. 115101ac1707SDuncan P. N. Exon Smith assert(Buffer.data() != 115201ac1707SDuncan P. N. Exon Smith SM.getMemoryBuffer(SM.FindBufferContainingLoc( 115301ac1707SDuncan P. N. Exon Smith SMLoc::getFromPointer(Buffer.data()))) 115401ac1707SDuncan P. N. Exon Smith ->getBufferStart() && 115501ac1707SDuncan P. N. Exon Smith "CHECK-SAME can't be the first check in a file"); 115601ac1707SDuncan P. N. Exon Smith 115701ac1707SDuncan P. N. Exon Smith const char *FirstNewLine = nullptr; 115801ac1707SDuncan P. N. Exon Smith unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 115901ac1707SDuncan P. N. Exon Smith 116001ac1707SDuncan P. N. Exon Smith if (NumNewLines != 0) { 116101ac1707SDuncan P. N. Exon Smith SM.PrintMessage(Loc, SourceMgr::DK_Error, 116201ac1707SDuncan P. N. Exon Smith Prefix + 116301ac1707SDuncan P. N. Exon Smith "-SAME: is not on the same line as the previous match"); 116401ac1707SDuncan P. N. Exon Smith SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 116501ac1707SDuncan P. N. Exon Smith "'next' match was here"); 116601ac1707SDuncan P. N. Exon Smith SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 116701ac1707SDuncan P. N. Exon Smith "previous match ended here"); 116801ac1707SDuncan P. N. Exon Smith return true; 116901ac1707SDuncan P. N. Exon Smith } 117001ac1707SDuncan P. N. Exon Smith 117101ac1707SDuncan P. N. Exon Smith return false; 117201ac1707SDuncan P. N. Exon Smith } 117301ac1707SDuncan P. N. Exon Smith 1174dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer, 117591a1b2c9SMichael Liao const std::vector<const Pattern *> &NotStrings, 1176dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const { 11778f870499SBenjamin Kramer for (const Pattern *Pat : NotStrings) { 117838820972SMatt Arsenault assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!"); 117991a1b2c9SMichael Liao 1180dcc7d48dSMichael Liao size_t MatchLen = 0; 118191a1b2c9SMichael Liao size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable); 1182dcc7d48dSMichael Liao 1183dcc7d48dSMichael Liao if (Pos == StringRef::npos) continue; 1184dcc7d48dSMichael Liao 1185dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos), 1186dcc7d48dSMichael Liao SourceMgr::DK_Error, 118713df4626SMatt Arsenault Prefix + "-NOT: string occurred!"); 118891a1b2c9SMichael Liao SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note, 118913df4626SMatt Arsenault Prefix + "-NOT: pattern specified here"); 1190dcc7d48dSMichael Liao return true; 1191dcc7d48dSMichael Liao } 1192dcc7d48dSMichael Liao 1193dcc7d48dSMichael Liao return false; 1194dcc7d48dSMichael Liao } 1195dcc7d48dSMichael Liao 119691a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, 119791a1b2c9SMichael Liao std::vector<const Pattern *> &NotStrings, 119891a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) const { 119991a1b2c9SMichael Liao if (DagNotStrings.empty()) 120091a1b2c9SMichael Liao return 0; 120191a1b2c9SMichael Liao 120291a1b2c9SMichael Liao size_t LastPos = 0; 120391a1b2c9SMichael Liao size_t StartPos = LastPos; 120491a1b2c9SMichael Liao 12058f870499SBenjamin Kramer for (const Pattern &Pat : DagNotStrings) { 120638820972SMatt Arsenault assert((Pat.getCheckTy() == Check::CheckDAG || 120738820972SMatt Arsenault Pat.getCheckTy() == Check::CheckNot) && 120891a1b2c9SMichael Liao "Invalid CHECK-DAG or CHECK-NOT!"); 120991a1b2c9SMichael Liao 121038820972SMatt Arsenault if (Pat.getCheckTy() == Check::CheckNot) { 121191a1b2c9SMichael Liao NotStrings.push_back(&Pat); 121291a1b2c9SMichael Liao continue; 121391a1b2c9SMichael Liao } 121491a1b2c9SMichael Liao 121538820972SMatt Arsenault assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!"); 121691a1b2c9SMichael Liao 121791a1b2c9SMichael Liao size_t MatchLen = 0, MatchPos; 121891a1b2c9SMichael Liao 121991a1b2c9SMichael Liao // CHECK-DAG always matches from the start. 122091a1b2c9SMichael Liao StringRef MatchBuffer = Buffer.substr(StartPos); 122191a1b2c9SMichael Liao MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); 122291a1b2c9SMichael Liao // With a group of CHECK-DAGs, a single mismatching means the match on 122391a1b2c9SMichael Liao // that group of CHECK-DAGs fails immediately. 122491a1b2c9SMichael Liao if (MatchPos == StringRef::npos) { 122591a1b2c9SMichael Liao PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable); 122691a1b2c9SMichael Liao return StringRef::npos; 122791a1b2c9SMichael Liao } 122891a1b2c9SMichael Liao // Re-calc it as the offset relative to the start of the original string. 122991a1b2c9SMichael Liao MatchPos += StartPos; 123091a1b2c9SMichael Liao 123191a1b2c9SMichael Liao if (!NotStrings.empty()) { 123291a1b2c9SMichael Liao if (MatchPos < LastPos) { 123391a1b2c9SMichael Liao // Reordered? 123491a1b2c9SMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos), 123591a1b2c9SMichael Liao SourceMgr::DK_Error, 123613df4626SMatt Arsenault Prefix + "-DAG: found a match of CHECK-DAG" 123791a1b2c9SMichael Liao " reordering across a CHECK-NOT"); 123891a1b2c9SMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos), 123991a1b2c9SMichael Liao SourceMgr::DK_Note, 124013df4626SMatt Arsenault Prefix + "-DAG: the farthest match of CHECK-DAG" 124191a1b2c9SMichael Liao " is found here"); 124291a1b2c9SMichael Liao SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note, 124313df4626SMatt Arsenault Prefix + "-NOT: the crossed pattern specified" 124491a1b2c9SMichael Liao " here"); 124591a1b2c9SMichael Liao SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note, 124613df4626SMatt Arsenault Prefix + "-DAG: the reordered pattern specified" 124791a1b2c9SMichael Liao " here"); 124891a1b2c9SMichael Liao return StringRef::npos; 124991a1b2c9SMichael Liao } 125091a1b2c9SMichael Liao // All subsequent CHECK-DAGs should be matched from the farthest 125191a1b2c9SMichael Liao // position of all precedent CHECK-DAGs (including this one.) 125291a1b2c9SMichael Liao StartPos = LastPos; 125391a1b2c9SMichael Liao // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to 125491a1b2c9SMichael Liao // CHECK-DAG, verify that there's no 'not' strings occurred in that 125591a1b2c9SMichael Liao // region. 125691a1b2c9SMichael Liao StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 1257cf708c32STim Northover if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) 125891a1b2c9SMichael Liao return StringRef::npos; 125991a1b2c9SMichael Liao // Clear "not strings". 126091a1b2c9SMichael Liao NotStrings.clear(); 126191a1b2c9SMichael Liao } 126291a1b2c9SMichael Liao 126391a1b2c9SMichael Liao // Update the last position with CHECK-DAG matches. 126491a1b2c9SMichael Liao LastPos = std::max(MatchPos + MatchLen, LastPos); 126591a1b2c9SMichael Liao } 126691a1b2c9SMichael Liao 126791a1b2c9SMichael Liao return LastPos; 126891a1b2c9SMichael Liao } 126991a1b2c9SMichael Liao 127013df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores. 127113df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) { 127213df4626SMatt Arsenault Regex Validator("^[a-zA-Z0-9_-]*$"); 127313df4626SMatt Arsenault return Validator.match(CheckPrefix); 127413df4626SMatt Arsenault } 127513df4626SMatt Arsenault 127613df4626SMatt Arsenault static bool ValidateCheckPrefixes() { 127713df4626SMatt Arsenault StringSet<> PrefixSet; 127813df4626SMatt Arsenault 12798f870499SBenjamin Kramer for (StringRef Prefix : CheckPrefixes) { 128024412b14SEli Bendersky // Reject empty prefixes. 128124412b14SEli Bendersky if (Prefix == "") 128224412b14SEli Bendersky return false; 128324412b14SEli Bendersky 12840356975cSDavid Blaikie if (!PrefixSet.insert(Prefix).second) 128513df4626SMatt Arsenault return false; 128613df4626SMatt Arsenault 128713df4626SMatt Arsenault if (!ValidateCheckPrefix(Prefix)) 128813df4626SMatt Arsenault return false; 128913df4626SMatt Arsenault } 129013df4626SMatt Arsenault 129113df4626SMatt Arsenault return true; 129213df4626SMatt Arsenault } 129313df4626SMatt Arsenault 129413df4626SMatt Arsenault // I don't think there's a way to specify an initial value for cl::list, 129513df4626SMatt Arsenault // so if nothing was specified, add the default 129613df4626SMatt Arsenault static void AddCheckPrefixIfNeeded() { 129713df4626SMatt Arsenault if (CheckPrefixes.empty()) 129813df4626SMatt Arsenault CheckPrefixes.push_back("CHECK"); 1299c2735158SRui Ueyama } 1300c2735158SRui Ueyama 1301ee3c74fbSChris Lattner int main(int argc, char **argv) { 1302ee3c74fbSChris Lattner sys::PrintStackTraceOnErrorSignal(); 1303ee3c74fbSChris Lattner PrettyStackTraceProgram X(argc, argv); 1304ee3c74fbSChris Lattner cl::ParseCommandLineOptions(argc, argv); 1305ee3c74fbSChris Lattner 130613df4626SMatt Arsenault if (!ValidateCheckPrefixes()) { 130713df4626SMatt Arsenault errs() << "Supplied check-prefix is invalid! Prefixes must be unique and " 130813df4626SMatt Arsenault "start with a letter and contain only alphanumeric characters, " 130913df4626SMatt Arsenault "hyphens and underscores\n"; 1310c2735158SRui Ueyama return 2; 1311c2735158SRui Ueyama } 1312c2735158SRui Ueyama 131313df4626SMatt Arsenault AddCheckPrefixIfNeeded(); 131413df4626SMatt Arsenault 1315ee3c74fbSChris Lattner SourceMgr SM; 1316ee3c74fbSChris Lattner 1317ee3c74fbSChris Lattner // Read the expected strings from the check file. 131826cccfe1SChris Lattner std::vector<CheckString> CheckStrings; 1319ee3c74fbSChris Lattner if (ReadCheckFile(SM, CheckStrings)) 1320ee3c74fbSChris Lattner return 2; 1321ee3c74fbSChris Lattner 1322ee3c74fbSChris Lattner // Open the file to check and add it to SourceMgr. 1323adf21f2aSRafael Espindola ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 1324adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(InputFilename); 1325adf21f2aSRafael Espindola if (std::error_code EC = FileOrErr.getError()) { 1326adf21f2aSRafael Espindola errs() << "Could not open input file '" << InputFilename 1327adf21f2aSRafael Espindola << "': " << EC.message() << '\n'; 13288e1c6477SEli Bendersky return 2; 1329ee3c74fbSChris Lattner } 13303f6481d0SRafael Espindola std::unique_ptr<MemoryBuffer> &File = FileOrErr.get(); 13312c3e5cdfSChris Lattner 13321b9f936fSJustin Bogner if (File->getBufferSize() == 0 && !AllowEmptyInput) { 1333b692bed7SChris Lattner errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 13348e1c6477SEli Bendersky return 2; 1335b692bed7SChris Lattner } 1336b692bed7SChris Lattner 13372c3e5cdfSChris Lattner // Remove duplicate spaces in the input file if requested. 13385ea04c38SGuy Benyei // Remove DOS style line endings. 13391961f14cSDavid Blaikie std::unique_ptr<MemoryBuffer> F = 1340ce5dd1acSRafael Espindola CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace); 13412c3e5cdfSChris Lattner 1342ee3c74fbSChris Lattner // Check that we have all of the expected strings, in order, in the input 1343ee3c74fbSChris Lattner // file. 1344caa5fc0cSChris Lattner StringRef Buffer = F->getBuffer(); 1345ee3c74fbSChris Lattner 13461961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(F), SMLoc()); 13471961f14cSDavid Blaikie 13481961f14cSDavid Blaikie /// VariableTable - This holds all the current filecheck variables. 13491961f14cSDavid Blaikie StringMap<StringRef> VariableTable; 13501961f14cSDavid Blaikie 1351f8bd2e5bSStephen Lin bool hasError = false; 1352ee3c74fbSChris Lattner 1353f8bd2e5bSStephen Lin unsigned i = 0, j = 0, e = CheckStrings.size(); 1354ee3c74fbSChris Lattner 1355f8bd2e5bSStephen Lin while (true) { 1356f8bd2e5bSStephen Lin StringRef CheckRegion; 1357f8bd2e5bSStephen Lin if (j == e) { 1358f8bd2e5bSStephen Lin CheckRegion = Buffer; 1359f8bd2e5bSStephen Lin } else { 1360f8bd2e5bSStephen Lin const CheckString &CheckLabelStr = CheckStrings[j]; 136185913ccaSJames Y Knight if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { 1362f8bd2e5bSStephen Lin ++j; 1363f8bd2e5bSStephen Lin continue; 1364da108b4eSChris Lattner } 1365da108b4eSChris Lattner 1366f8bd2e5bSStephen Lin // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG 1367f8bd2e5bSStephen Lin size_t MatchLabelLen = 0; 1368e93a3a08SStephen Lin size_t MatchLabelPos = CheckLabelStr.Check(SM, Buffer, true, 1369f8bd2e5bSStephen Lin MatchLabelLen, VariableTable); 1370f8bd2e5bSStephen Lin if (MatchLabelPos == StringRef::npos) { 1371f8bd2e5bSStephen Lin hasError = true; 1372f8bd2e5bSStephen Lin break; 1373f8bd2e5bSStephen Lin } 1374f8bd2e5bSStephen Lin 1375f8bd2e5bSStephen Lin CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen); 1376f8bd2e5bSStephen Lin Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen); 1377f8bd2e5bSStephen Lin ++j; 1378f8bd2e5bSStephen Lin } 1379f8bd2e5bSStephen Lin 1380f8bd2e5bSStephen Lin for ( ; i != j; ++i) { 1381f8bd2e5bSStephen Lin const CheckString &CheckStr = CheckStrings[i]; 1382f8bd2e5bSStephen Lin 1383f8bd2e5bSStephen Lin // Check each string within the scanned region, including a second check 1384f8bd2e5bSStephen Lin // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) 1385f8bd2e5bSStephen Lin size_t MatchLen = 0; 1386e93a3a08SStephen Lin size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen, 1387f8bd2e5bSStephen Lin VariableTable); 1388f8bd2e5bSStephen Lin 1389f8bd2e5bSStephen Lin if (MatchPos == StringRef::npos) { 1390f8bd2e5bSStephen Lin hasError = true; 1391f8bd2e5bSStephen Lin i = j; 1392f8bd2e5bSStephen Lin break; 1393f8bd2e5bSStephen Lin } 1394f8bd2e5bSStephen Lin 1395f8bd2e5bSStephen Lin CheckRegion = CheckRegion.substr(MatchPos + MatchLen); 1396f8bd2e5bSStephen Lin } 1397f8bd2e5bSStephen Lin 1398f8bd2e5bSStephen Lin if (j == e) 1399f8bd2e5bSStephen Lin break; 1400f8bd2e5bSStephen Lin } 1401f8bd2e5bSStephen Lin 1402f8bd2e5bSStephen Lin return hasError ? 1 : 0; 1403ee3c74fbSChris Lattner } 1404