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')")); 48fd557cb0SDaniel Sanders static cl::alias CheckPrefixesAlias( 49fd557cb0SDaniel Sanders "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated, 50fd557cb0SDaniel Sanders cl::NotHidden, 51fd557cb0SDaniel Sanders cl::desc( 52fd557cb0SDaniel Sanders "Alias for -check-prefix permitting multiple comma separated values")); 53ee3c74fbSChris Lattner 542c3e5cdfSChris Lattner static cl::opt<bool> 552c3e5cdfSChris Lattner NoCanonicalizeWhiteSpace("strict-whitespace", 562c3e5cdfSChris Lattner cl::desc("Do not treat all horizontal whitespace as equivalent")); 572c3e5cdfSChris Lattner 5856ccdbbdSAlexander Kornienko static cl::list<std::string> ImplicitCheckNot( 5956ccdbbdSAlexander Kornienko "implicit-check-not", 6056ccdbbdSAlexander Kornienko cl::desc("Add an implicit negative check with this pattern to every\n" 6156ccdbbdSAlexander Kornienko "positive check. This can be used to ensure that no instances of\n" 6256ccdbbdSAlexander Kornienko "this pattern occur which are not matched by a positive pattern"), 6356ccdbbdSAlexander Kornienko cl::value_desc("pattern")); 6456ccdbbdSAlexander Kornienko 651b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput( 661b9f936fSJustin Bogner "allow-empty", cl::init(false), 671b9f936fSJustin Bogner cl::desc("Allow the input file to be empty. This is useful when making\n" 681b9f936fSJustin Bogner "checks that some error message does not occur, for example.")); 691b9f936fSJustin Bogner 7085913ccaSJames Y Knight static cl::opt<bool> MatchFullLines( 7185913ccaSJames Y Knight "match-full-lines", cl::init(false), 7285913ccaSJames Y Knight cl::desc("Require all positive matches to cover an entire input line.\n" 7385913ccaSJames Y Knight "Allows leading and trailing whitespace if --strict-whitespace\n" 7485913ccaSJames Y Knight "is not also passed.")); 7585913ccaSJames Y Knight 7613df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator; 7713df4626SMatt Arsenault 7874d50731SChris Lattner //===----------------------------------------------------------------------===// 7974d50731SChris Lattner // Pattern Handling Code. 8074d50731SChris Lattner //===----------------------------------------------------------------------===// 8174d50731SChris Lattner 8238820972SMatt Arsenault namespace Check { 8338820972SMatt Arsenault enum CheckType { 8438820972SMatt Arsenault CheckNone = 0, 8538820972SMatt Arsenault CheckPlain, 8638820972SMatt Arsenault CheckNext, 8701ac1707SDuncan P. N. Exon Smith CheckSame, 8838820972SMatt Arsenault CheckNot, 8938820972SMatt Arsenault CheckDAG, 9038820972SMatt Arsenault CheckLabel, 910a4c44bdSChris Lattner 92eba55822SJakob Stoklund Olesen /// MatchEOF - When set, this pattern only matches the end of file. This is 93eba55822SJakob Stoklund Olesen /// used for trailing CHECK-NOTs. 94a908e7bdSPaul Robinson CheckEOF, 95a908e7bdSPaul Robinson /// CheckBadNot - Found -NOT combined with another CHECK suffix. 96a908e7bdSPaul Robinson CheckBadNot 9738820972SMatt Arsenault }; 9838820972SMatt Arsenault } 99eba55822SJakob Stoklund Olesen 10038820972SMatt Arsenault class Pattern { 10138820972SMatt Arsenault SMLoc PatternLoc; 10291a1b2c9SMichael Liao 103b16ab0c4SChris Lattner /// FixedStr - If non-empty, this pattern is a fixed string match with the 104b16ab0c4SChris Lattner /// specified fixed string. 105221460e0SChris Lattner StringRef FixedStr; 106b16ab0c4SChris Lattner 107b16ab0c4SChris Lattner /// RegEx - If non-empty, this is a regex pattern. 108b16ab0c4SChris Lattner std::string RegExStr; 1098879e06dSChris Lattner 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 121*d1e020f7SSaleem Abdulrasool Check::CheckType CheckTy; 1223b40b445SChris Lattner 123*d1e020f7SSaleem Abdulrasool /// \brief Contains the number of line this pattern is in. 124*d1e020f7SSaleem Abdulrasool unsigned LineNumber; 125*d1e020f7SSaleem Abdulrasool 126*d1e020f7SSaleem Abdulrasool public: 127*d1e020f7SSaleem Abdulrasool explicit Pattern(Check::CheckType Ty) : CheckTy(Ty) {} 12874d50731SChris Lattner 1290b707eb8SMichael Liao /// getLoc - Return the location in source code. 1300b707eb8SMichael Liao SMLoc getLoc() const { return PatternLoc; } 1310b707eb8SMichael Liao 13213df4626SMatt Arsenault /// ParsePattern - Parse the given string into the Pattern. Prefix provides 13313df4626SMatt Arsenault /// which prefix is being matched, SM provides the SourceMgr used for error 13413df4626SMatt Arsenault /// reports, and LineNumber is the line number in the input file from which 13513df4626SMatt Arsenault /// the pattern string was read. Returns true in case of an error, false 13613df4626SMatt Arsenault /// otherwise. 13713df4626SMatt Arsenault bool ParsePattern(StringRef PatternStr, 13813df4626SMatt Arsenault StringRef Prefix, 13913df4626SMatt Arsenault SourceMgr &SM, 14013df4626SMatt Arsenault unsigned LineNumber); 1413b40b445SChris Lattner 1423b40b445SChris Lattner /// Match - Match the pattern string against the input buffer Buffer. This 1433b40b445SChris Lattner /// returns the position that is matched or npos if there is no match. If 1443b40b445SChris Lattner /// there is a match, the size of the matched string is returned in MatchLen. 1458879e06dSChris Lattner /// 1468879e06dSChris Lattner /// The VariableTable StringMap provides the current values of filecheck 1478879e06dSChris Lattner /// variables and is updated if this match defines new values. 1488879e06dSChris Lattner size_t Match(StringRef Buffer, size_t &MatchLen, 1498879e06dSChris Lattner StringMap<StringRef> &VariableTable) const; 150b16ab0c4SChris Lattner 151e0ef65abSDaniel Dunbar /// PrintFailureInfo - Print additional information about a failure to match 152e0ef65abSDaniel Dunbar /// involving this pattern. 153e0ef65abSDaniel Dunbar void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 154e0ef65abSDaniel Dunbar const StringMap<StringRef> &VariableTable) const; 155e0ef65abSDaniel Dunbar 156f8bd2e5bSStephen Lin bool hasVariable() const { return !(VariableUses.empty() && 157f8bd2e5bSStephen Lin VariableDefs.empty()); } 158f8bd2e5bSStephen Lin 15938820972SMatt Arsenault Check::CheckType getCheckTy() const { return CheckTy; } 16091a1b2c9SMichael Liao 161b16ab0c4SChris Lattner private: 162e8b8f1bcSEli Bendersky bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); 163e8b8f1bcSEli Bendersky void AddBackrefToRegEx(unsigned BackrefNum); 164fd29d886SDaniel Dunbar 165fd29d886SDaniel Dunbar /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of 166fd29d886SDaniel Dunbar /// matching this pattern at the start of \arg Buffer; a distance of zero 167fd29d886SDaniel Dunbar /// should correspond to a perfect match. 168fd29d886SDaniel Dunbar unsigned ComputeMatchDistance(StringRef Buffer, 169fd29d886SDaniel Dunbar const StringMap<StringRef> &VariableTable) const; 17092987fb3SAlexander Kornienko 17192987fb3SAlexander Kornienko /// \brief Evaluates expression and stores the result to \p Value. 17292987fb3SAlexander Kornienko /// \return true on success. false when the expression has invalid syntax. 17392987fb3SAlexander Kornienko bool EvaluateExpression(StringRef Expr, std::string &Value) const; 174061d2baaSEli Bendersky 175061d2baaSEli Bendersky /// \brief Finds the closing sequence of a regex variable usage or 176061d2baaSEli Bendersky /// definition. Str has to point in the beginning of the definition 177061d2baaSEli Bendersky /// (right after the opening sequence). 178061d2baaSEli Bendersky /// \return offset of the closing sequence within Str, or npos if it was not 179061d2baaSEli Bendersky /// found. 18081e5cd9eSAdrian Prantl size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); 1813b40b445SChris Lattner }; 1823b40b445SChris Lattner 1838879e06dSChris Lattner 18413df4626SMatt Arsenault bool Pattern::ParsePattern(StringRef PatternStr, 18513df4626SMatt Arsenault StringRef Prefix, 18613df4626SMatt Arsenault SourceMgr &SM, 18792987fb3SAlexander Kornienko unsigned LineNumber) { 18885913ccaSJames Y Knight bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot; 18985913ccaSJames Y Knight 19092987fb3SAlexander Kornienko this->LineNumber = LineNumber; 1910a4c44bdSChris Lattner PatternLoc = SMLoc::getFromPointer(PatternStr.data()); 1920a4c44bdSChris Lattner 19374d50731SChris Lattner // Ignore trailing whitespace. 19474d50731SChris Lattner while (!PatternStr.empty() && 19574d50731SChris Lattner (PatternStr.back() == ' ' || PatternStr.back() == '\t')) 19674d50731SChris Lattner PatternStr = PatternStr.substr(0, PatternStr.size()-1); 19774d50731SChris Lattner 19874d50731SChris Lattner // Check that there is something on the line. 19974d50731SChris Lattner if (PatternStr.empty()) { 20003b80a40SChris Lattner SM.PrintMessage(PatternLoc, SourceMgr::DK_Error, 20103b80a40SChris Lattner "found empty check string with prefix '" + 20213df4626SMatt Arsenault Prefix + ":'"); 20374d50731SChris Lattner return true; 20474d50731SChris Lattner } 20574d50731SChris Lattner 206221460e0SChris Lattner // Check to see if this is a fixed string, or if it has regex pieces. 20785913ccaSJames Y Knight if (!MatchFullLinesHere && 20885913ccaSJames Y Knight (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && 20985913ccaSJames Y Knight PatternStr.find("[[") == StringRef::npos))) { 210221460e0SChris Lattner FixedStr = PatternStr; 211221460e0SChris Lattner return false; 212221460e0SChris Lattner } 213221460e0SChris Lattner 21485913ccaSJames Y Knight if (MatchFullLinesHere) { 21585913ccaSJames Y Knight RegExStr += '^'; 21685913ccaSJames Y Knight if (!NoCanonicalizeWhiteSpace) 21785913ccaSJames Y Knight RegExStr += " *"; 21885913ccaSJames Y Knight } 21985913ccaSJames Y Knight 2208879e06dSChris Lattner // Paren value #0 is for the fully matched string. Any new parenthesized 22153e0679dSChris Lattner // values add from there. 2228879e06dSChris Lattner unsigned CurParen = 1; 2238879e06dSChris Lattner 224b16ab0c4SChris Lattner // Otherwise, there is at least one regex piece. Build up the regex pattern 225b16ab0c4SChris Lattner // by escaping scary characters in fixed strings, building up one big regex. 226f08d2db9SChris Lattner while (!PatternStr.empty()) { 2278879e06dSChris Lattner // RegEx matches. 22853e0679dSChris Lattner if (PatternStr.startswith("{{")) { 22943d50d4aSEli Bendersky // This is the start of a regex match. Scan for the }}. 230f08d2db9SChris Lattner size_t End = PatternStr.find("}}"); 231f08d2db9SChris Lattner if (End == StringRef::npos) { 232f08d2db9SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 23303b80a40SChris Lattner SourceMgr::DK_Error, 23403b80a40SChris Lattner "found start of regex string with no end '}}'"); 235f08d2db9SChris Lattner return true; 236f08d2db9SChris Lattner } 237f08d2db9SChris Lattner 238e53c95f1SChris Lattner // Enclose {{}} patterns in parens just like [[]] even though we're not 239e53c95f1SChris Lattner // capturing the result for any purpose. This is required in case the 240e53c95f1SChris Lattner // expression contains an alternation like: CHECK: abc{{x|z}}def. We 241e53c95f1SChris Lattner // want this to turn into: "abc(x|z)def" not "abcx|zdef". 242e53c95f1SChris Lattner RegExStr += '('; 243e53c95f1SChris Lattner ++CurParen; 244e53c95f1SChris Lattner 2458879e06dSChris Lattner if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) 2468879e06dSChris Lattner return true; 247e53c95f1SChris Lattner RegExStr += ')'; 24853e0679dSChris Lattner 2498879e06dSChris Lattner PatternStr = PatternStr.substr(End+2); 2508879e06dSChris Lattner continue; 2518879e06dSChris Lattner } 2528879e06dSChris Lattner 2538879e06dSChris Lattner // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* 2548879e06dSChris Lattner // (or some other regex) and assigns it to the FileCheck variable 'foo'. The 2558879e06dSChris Lattner // second form is [[foo]] which is a reference to foo. The variable name 25657cb733bSDaniel Dunbar // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject 2578879e06dSChris Lattner // it. This is to catch some common errors. 25853e0679dSChris Lattner if (PatternStr.startswith("[[")) { 259061d2baaSEli Bendersky // Find the closing bracket pair ending the match. End is going to be an 260061d2baaSEli Bendersky // offset relative to the beginning of the match string. 26181e5cd9eSAdrian Prantl size_t End = FindRegexVarEnd(PatternStr.substr(2), SM); 262061d2baaSEli Bendersky 2638879e06dSChris Lattner if (End == StringRef::npos) { 2648879e06dSChris Lattner SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 26503b80a40SChris Lattner SourceMgr::DK_Error, 26603b80a40SChris Lattner "invalid named regex reference, no ]] found"); 267f08d2db9SChris Lattner return true; 268f08d2db9SChris Lattner } 269f08d2db9SChris Lattner 270061d2baaSEli Bendersky StringRef MatchStr = PatternStr.substr(2, End); 271061d2baaSEli Bendersky PatternStr = PatternStr.substr(End+4); 2728879e06dSChris Lattner 2738879e06dSChris Lattner // Get the regex name (e.g. "foo"). 2748879e06dSChris Lattner size_t NameEnd = MatchStr.find(':'); 2758879e06dSChris Lattner StringRef Name = MatchStr.substr(0, NameEnd); 2768879e06dSChris Lattner 2778879e06dSChris Lattner if (Name.empty()) { 27803b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 27903b80a40SChris Lattner "invalid name in named regex: empty name"); 2808879e06dSChris Lattner return true; 2818879e06dSChris Lattner } 2828879e06dSChris Lattner 28392987fb3SAlexander Kornienko // Verify that the name/expression is well formed. FileCheck currently 28492987fb3SAlexander Kornienko // supports @LINE, @LINE+number, @LINE-number expressions. The check here 28592987fb3SAlexander Kornienko // is relaxed, more strict check is performed in \c EvaluateExpression. 28692987fb3SAlexander Kornienko bool IsExpression = false; 28792987fb3SAlexander Kornienko for (unsigned i = 0, e = Name.size(); i != e; ++i) { 28892987fb3SAlexander Kornienko if (i == 0 && Name[i] == '@') { 28992987fb3SAlexander Kornienko if (NameEnd != StringRef::npos) { 29092987fb3SAlexander Kornienko SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 29192987fb3SAlexander Kornienko SourceMgr::DK_Error, 29292987fb3SAlexander Kornienko "invalid name in named regex definition"); 29392987fb3SAlexander Kornienko return true; 29492987fb3SAlexander Kornienko } 29592987fb3SAlexander Kornienko IsExpression = true; 29692987fb3SAlexander Kornienko continue; 29792987fb3SAlexander Kornienko } 29892987fb3SAlexander Kornienko if (Name[i] != '_' && !isalnum(Name[i]) && 29992987fb3SAlexander Kornienko (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) { 3008879e06dSChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), 30103b80a40SChris Lattner SourceMgr::DK_Error, "invalid name in named regex"); 3028879e06dSChris Lattner return true; 3038879e06dSChris Lattner } 30492987fb3SAlexander Kornienko } 3058879e06dSChris Lattner 3068879e06dSChris Lattner // Name can't start with a digit. 30783c74e9fSGuy Benyei if (isdigit(static_cast<unsigned char>(Name[0]))) { 30803b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 30903b80a40SChris Lattner "invalid name in named regex"); 3108879e06dSChris Lattner return true; 3118879e06dSChris Lattner } 3128879e06dSChris Lattner 3138879e06dSChris Lattner // Handle [[foo]]. 3148879e06dSChris Lattner if (NameEnd == StringRef::npos) { 315e8b8f1bcSEli Bendersky // Handle variables that were defined earlier on the same line by 316e8b8f1bcSEli Bendersky // emitting a backreference. 317e8b8f1bcSEli Bendersky if (VariableDefs.find(Name) != VariableDefs.end()) { 318e8b8f1bcSEli Bendersky unsigned VarParenNum = VariableDefs[Name]; 319e8b8f1bcSEli Bendersky if (VarParenNum < 1 || VarParenNum > 9) { 320e8b8f1bcSEli Bendersky SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 321e8b8f1bcSEli Bendersky SourceMgr::DK_Error, 322e8b8f1bcSEli Bendersky "Can't back-reference more than 9 variables"); 323e8b8f1bcSEli Bendersky return true; 324e8b8f1bcSEli Bendersky } 325e8b8f1bcSEli Bendersky AddBackrefToRegEx(VarParenNum); 326e8b8f1bcSEli Bendersky } else { 3278879e06dSChris Lattner VariableUses.push_back(std::make_pair(Name, RegExStr.size())); 328e8b8f1bcSEli Bendersky } 3298879e06dSChris Lattner continue; 3308879e06dSChris Lattner } 3318879e06dSChris Lattner 3328879e06dSChris Lattner // Handle [[foo:.*]]. 333e8b8f1bcSEli Bendersky VariableDefs[Name] = CurParen; 3348879e06dSChris Lattner RegExStr += '('; 3358879e06dSChris Lattner ++CurParen; 3368879e06dSChris Lattner 3378879e06dSChris Lattner if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) 3388879e06dSChris Lattner return true; 3398879e06dSChris Lattner 3408879e06dSChris Lattner RegExStr += ')'; 3418879e06dSChris Lattner } 3428879e06dSChris Lattner 3438879e06dSChris Lattner // Handle fixed string matches. 3448879e06dSChris Lattner // Find the end, which is the start of the next regex. 3458879e06dSChris Lattner size_t FixedMatchEnd = PatternStr.find("{{"); 3468879e06dSChris Lattner FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); 3476f4f77b7SHans Wennborg RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd)); 3488879e06dSChris Lattner PatternStr = PatternStr.substr(FixedMatchEnd); 349f08d2db9SChris Lattner } 350f08d2db9SChris Lattner 35185913ccaSJames Y Knight if (MatchFullLinesHere) { 35285913ccaSJames Y Knight if (!NoCanonicalizeWhiteSpace) 35385913ccaSJames Y Knight RegExStr += " *"; 35485913ccaSJames Y Knight RegExStr += '$'; 35585913ccaSJames Y Knight } 35685913ccaSJames Y Knight 35774d50731SChris Lattner return false; 35874d50731SChris Lattner } 35974d50731SChris Lattner 360e8b8f1bcSEli Bendersky bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, 3618879e06dSChris Lattner SourceMgr &SM) { 362e8b8f1bcSEli Bendersky Regex R(RS); 3638879e06dSChris Lattner std::string Error; 3648879e06dSChris Lattner if (!R.isValid(Error)) { 365e8b8f1bcSEli Bendersky SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error, 36603b80a40SChris Lattner "invalid regex: " + Error); 3678879e06dSChris Lattner return true; 3688879e06dSChris Lattner } 3698879e06dSChris Lattner 370e8b8f1bcSEli Bendersky RegExStr += RS.str(); 3718879e06dSChris Lattner CurParen += R.getNumMatches(); 3728879e06dSChris Lattner return false; 3738879e06dSChris Lattner } 374b16ab0c4SChris Lattner 375e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) { 376e8b8f1bcSEli Bendersky assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number"); 377e8b8f1bcSEli Bendersky std::string Backref = std::string("\\") + 378e8b8f1bcSEli Bendersky std::string(1, '0' + BackrefNum); 379e8b8f1bcSEli Bendersky RegExStr += Backref; 380e8b8f1bcSEli Bendersky } 381e8b8f1bcSEli Bendersky 38292987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const { 38392987fb3SAlexander Kornienko // The only supported expression is @LINE([\+-]\d+)? 38492987fb3SAlexander Kornienko if (!Expr.startswith("@LINE")) 38592987fb3SAlexander Kornienko return false; 38692987fb3SAlexander Kornienko Expr = Expr.substr(StringRef("@LINE").size()); 38792987fb3SAlexander Kornienko int Offset = 0; 38892987fb3SAlexander Kornienko if (!Expr.empty()) { 38992987fb3SAlexander Kornienko if (Expr[0] == '+') 39092987fb3SAlexander Kornienko Expr = Expr.substr(1); 39192987fb3SAlexander Kornienko else if (Expr[0] != '-') 39292987fb3SAlexander Kornienko return false; 39392987fb3SAlexander Kornienko if (Expr.getAsInteger(10, Offset)) 39492987fb3SAlexander Kornienko return false; 39592987fb3SAlexander Kornienko } 39692987fb3SAlexander Kornienko Value = llvm::itostr(LineNumber + Offset); 39792987fb3SAlexander Kornienko return true; 39892987fb3SAlexander Kornienko } 39992987fb3SAlexander Kornienko 400f08d2db9SChris Lattner /// Match - Match the pattern string against the input buffer Buffer. This 401f08d2db9SChris Lattner /// returns the position that is matched or npos if there is no match. If 402f08d2db9SChris Lattner /// there is a match, the size of the matched string is returned in MatchLen. 4038879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, 4048879e06dSChris Lattner StringMap<StringRef> &VariableTable) const { 405eba55822SJakob Stoklund Olesen // If this is the EOF pattern, match it immediately. 40638820972SMatt Arsenault if (CheckTy == Check::CheckEOF) { 407eba55822SJakob Stoklund Olesen MatchLen = 0; 408eba55822SJakob Stoklund Olesen return Buffer.size(); 409eba55822SJakob Stoklund Olesen } 410eba55822SJakob Stoklund Olesen 411221460e0SChris Lattner // If this is a fixed string pattern, just match it now. 412221460e0SChris Lattner if (!FixedStr.empty()) { 413221460e0SChris Lattner MatchLen = FixedStr.size(); 414221460e0SChris Lattner return Buffer.find(FixedStr); 415221460e0SChris Lattner } 416221460e0SChris Lattner 417b16ab0c4SChris Lattner // Regex match. 4188879e06dSChris Lattner 4198879e06dSChris Lattner // If there are variable uses, we need to create a temporary string with the 4208879e06dSChris Lattner // actual value. 4218879e06dSChris Lattner StringRef RegExToMatch = RegExStr; 4228879e06dSChris Lattner std::string TmpStr; 4238879e06dSChris Lattner if (!VariableUses.empty()) { 4248879e06dSChris Lattner TmpStr = RegExStr; 4258879e06dSChris Lattner 4268879e06dSChris Lattner unsigned InsertOffset = 0; 4278f870499SBenjamin Kramer for (const auto &VariableUse : VariableUses) { 42892987fb3SAlexander Kornienko std::string Value; 42992987fb3SAlexander Kornienko 4308f870499SBenjamin Kramer if (VariableUse.first[0] == '@') { 4318f870499SBenjamin Kramer if (!EvaluateExpression(VariableUse.first, Value)) 43292987fb3SAlexander Kornienko return StringRef::npos; 43392987fb3SAlexander Kornienko } else { 434e0ef65abSDaniel Dunbar StringMap<StringRef>::iterator it = 4358f870499SBenjamin Kramer VariableTable.find(VariableUse.first); 436e0ef65abSDaniel Dunbar // If the variable is undefined, return an error. 437e0ef65abSDaniel Dunbar if (it == VariableTable.end()) 438e0ef65abSDaniel Dunbar return StringRef::npos; 439e0ef65abSDaniel Dunbar 4406f4f77b7SHans Wennborg // Look up the value and escape it so that we can put it into the regex. 4416f4f77b7SHans Wennborg Value += Regex::escape(it->second); 44292987fb3SAlexander Kornienko } 4438879e06dSChris Lattner 4448879e06dSChris Lattner // Plop it into the regex at the adjusted offset. 4458f870499SBenjamin Kramer TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset, 4468879e06dSChris Lattner Value.begin(), Value.end()); 4478879e06dSChris Lattner InsertOffset += Value.size(); 4488879e06dSChris Lattner } 4498879e06dSChris Lattner 4508879e06dSChris Lattner // Match the newly constructed regex. 4518879e06dSChris Lattner RegExToMatch = TmpStr; 4528879e06dSChris Lattner } 4538879e06dSChris Lattner 4548879e06dSChris Lattner 455b16ab0c4SChris Lattner SmallVector<StringRef, 4> MatchInfo; 4568879e06dSChris Lattner if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo)) 457f08d2db9SChris Lattner return StringRef::npos; 458b16ab0c4SChris Lattner 459b16ab0c4SChris Lattner // Successful regex match. 460b16ab0c4SChris Lattner assert(!MatchInfo.empty() && "Didn't get any match"); 461b16ab0c4SChris Lattner StringRef FullMatch = MatchInfo[0]; 462b16ab0c4SChris Lattner 4638879e06dSChris Lattner // If this defines any variables, remember their values. 4648f870499SBenjamin Kramer for (const auto &VariableDef : VariableDefs) { 4658f870499SBenjamin Kramer assert(VariableDef.second < MatchInfo.size() && "Internal paren error"); 4668f870499SBenjamin Kramer VariableTable[VariableDef.first] = MatchInfo[VariableDef.second]; 4670a4c44bdSChris Lattner } 4680a4c44bdSChris Lattner 469b16ab0c4SChris Lattner MatchLen = FullMatch.size(); 470b16ab0c4SChris Lattner return FullMatch.data()-Buffer.data(); 471f08d2db9SChris Lattner } 472f08d2db9SChris Lattner 473fd29d886SDaniel Dunbar unsigned Pattern::ComputeMatchDistance(StringRef Buffer, 474fd29d886SDaniel Dunbar const StringMap<StringRef> &VariableTable) const { 475fd29d886SDaniel Dunbar // Just compute the number of matching characters. For regular expressions, we 476fd29d886SDaniel Dunbar // just compare against the regex itself and hope for the best. 477fd29d886SDaniel Dunbar // 478fd29d886SDaniel Dunbar // FIXME: One easy improvement here is have the regex lib generate a single 479fd29d886SDaniel Dunbar // example regular expression which matches, and use that as the example 480fd29d886SDaniel Dunbar // string. 481fd29d886SDaniel Dunbar StringRef ExampleString(FixedStr); 482fd29d886SDaniel Dunbar if (ExampleString.empty()) 483fd29d886SDaniel Dunbar ExampleString = RegExStr; 484fd29d886SDaniel Dunbar 485e9aa36c8SDaniel Dunbar // Only compare up to the first line in the buffer, or the string size. 486e9aa36c8SDaniel Dunbar StringRef BufferPrefix = Buffer.substr(0, ExampleString.size()); 487e9aa36c8SDaniel Dunbar BufferPrefix = BufferPrefix.split('\n').first; 488e9aa36c8SDaniel Dunbar return BufferPrefix.edit_distance(ExampleString); 489fd29d886SDaniel Dunbar } 490fd29d886SDaniel Dunbar 491e0ef65abSDaniel Dunbar void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 492e0ef65abSDaniel Dunbar const StringMap<StringRef> &VariableTable) const{ 493e0ef65abSDaniel Dunbar // If this was a regular expression using variables, print the current 494e0ef65abSDaniel Dunbar // variable values. 495e0ef65abSDaniel Dunbar if (!VariableUses.empty()) { 4968f870499SBenjamin Kramer for (const auto &VariableUse : VariableUses) { 497e69170a1SAlp Toker SmallString<256> Msg; 498e69170a1SAlp Toker raw_svector_ostream OS(Msg); 4998f870499SBenjamin Kramer StringRef Var = VariableUse.first; 50092987fb3SAlexander Kornienko if (Var[0] == '@') { 50192987fb3SAlexander Kornienko std::string Value; 50292987fb3SAlexander Kornienko if (EvaluateExpression(Var, Value)) { 50392987fb3SAlexander Kornienko OS << "with expression \""; 50492987fb3SAlexander Kornienko OS.write_escaped(Var) << "\" equal to \""; 50592987fb3SAlexander Kornienko OS.write_escaped(Value) << "\""; 50692987fb3SAlexander Kornienko } else { 50792987fb3SAlexander Kornienko OS << "uses incorrect expression \""; 50892987fb3SAlexander Kornienko OS.write_escaped(Var) << "\""; 50992987fb3SAlexander Kornienko } 51092987fb3SAlexander Kornienko } else { 51192987fb3SAlexander Kornienko StringMap<StringRef>::const_iterator it = VariableTable.find(Var); 512e0ef65abSDaniel Dunbar 513e0ef65abSDaniel Dunbar // Check for undefined variable references. 514e0ef65abSDaniel Dunbar if (it == VariableTable.end()) { 515e0ef65abSDaniel Dunbar OS << "uses undefined variable \""; 51692987fb3SAlexander Kornienko OS.write_escaped(Var) << "\""; 517e0ef65abSDaniel Dunbar } else { 518e0ef65abSDaniel Dunbar OS << "with variable \""; 519e0ef65abSDaniel Dunbar OS.write_escaped(Var) << "\" equal to \""; 520e0ef65abSDaniel Dunbar OS.write_escaped(it->second) << "\""; 521e0ef65abSDaniel Dunbar } 52292987fb3SAlexander Kornienko } 523e0ef65abSDaniel Dunbar 52403b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 52503b80a40SChris Lattner OS.str()); 526e0ef65abSDaniel Dunbar } 527e0ef65abSDaniel Dunbar } 528fd29d886SDaniel Dunbar 529fd29d886SDaniel Dunbar // Attempt to find the closest/best fuzzy match. Usually an error happens 530fd29d886SDaniel Dunbar // because some string in the output didn't exactly match. In these cases, we 531fd29d886SDaniel Dunbar // would like to show the user a best guess at what "should have" matched, to 532fd29d886SDaniel Dunbar // save them having to actually check the input manually. 533fd29d886SDaniel Dunbar size_t NumLinesForward = 0; 534fd29d886SDaniel Dunbar size_t Best = StringRef::npos; 535fd29d886SDaniel Dunbar double BestQuality = 0; 536fd29d886SDaniel Dunbar 537fd29d886SDaniel Dunbar // Use an arbitrary 4k limit on how far we will search. 5382bf486ebSDan Gohman for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { 539fd29d886SDaniel Dunbar if (Buffer[i] == '\n') 540fd29d886SDaniel Dunbar ++NumLinesForward; 541fd29d886SDaniel Dunbar 542df22bbf7SDan Gohman // Patterns have leading whitespace stripped, so skip whitespace when 543df22bbf7SDan Gohman // looking for something which looks like a pattern. 544df22bbf7SDan Gohman if (Buffer[i] == ' ' || Buffer[i] == '\t') 545df22bbf7SDan Gohman continue; 546df22bbf7SDan Gohman 547fd29d886SDaniel Dunbar // Compute the "quality" of this match as an arbitrary combination of the 548fd29d886SDaniel Dunbar // match distance and the number of lines skipped to get to this match. 549fd29d886SDaniel Dunbar unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); 550fd29d886SDaniel Dunbar double Quality = Distance + (NumLinesForward / 100.); 551fd29d886SDaniel Dunbar 552fd29d886SDaniel Dunbar if (Quality < BestQuality || Best == StringRef::npos) { 553fd29d886SDaniel Dunbar Best = i; 554fd29d886SDaniel Dunbar BestQuality = Quality; 555fd29d886SDaniel Dunbar } 556fd29d886SDaniel Dunbar } 557fd29d886SDaniel Dunbar 558fd29d886SDaniel Dunbar // Print the "possible intended match here" line if we found something 559c069cc8eSDaniel Dunbar // reasonable and not equal to what we showed in the "scanning from here" 560c069cc8eSDaniel Dunbar // line. 561c069cc8eSDaniel Dunbar if (Best && Best != StringRef::npos && BestQuality < 50) { 562fd29d886SDaniel Dunbar SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), 56303b80a40SChris Lattner SourceMgr::DK_Note, "possible intended match here"); 564fd29d886SDaniel Dunbar 565fd29d886SDaniel Dunbar // FIXME: If we wanted to be really friendly we would show why the match 566fd29d886SDaniel Dunbar // failed, as it can be hard to spot simple one character differences. 567fd29d886SDaniel Dunbar } 568e0ef65abSDaniel Dunbar } 56974d50731SChris Lattner 57081e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { 571061d2baaSEli Bendersky // Offset keeps track of the current offset within the input Str 572061d2baaSEli Bendersky size_t Offset = 0; 573061d2baaSEli Bendersky // [...] Nesting depth 574061d2baaSEli Bendersky size_t BracketDepth = 0; 575061d2baaSEli Bendersky 576061d2baaSEli Bendersky while (!Str.empty()) { 577061d2baaSEli Bendersky if (Str.startswith("]]") && BracketDepth == 0) 578061d2baaSEli Bendersky return Offset; 579061d2baaSEli Bendersky if (Str[0] == '\\') { 580061d2baaSEli Bendersky // Backslash escapes the next char within regexes, so skip them both. 581061d2baaSEli Bendersky Str = Str.substr(2); 582061d2baaSEli Bendersky Offset += 2; 583061d2baaSEli Bendersky } else { 584061d2baaSEli Bendersky switch (Str[0]) { 585061d2baaSEli Bendersky default: 586061d2baaSEli Bendersky break; 587061d2baaSEli Bendersky case '[': 588061d2baaSEli Bendersky BracketDepth++; 589061d2baaSEli Bendersky break; 590061d2baaSEli Bendersky case ']': 59181e5cd9eSAdrian Prantl if (BracketDepth == 0) { 59281e5cd9eSAdrian Prantl SM.PrintMessage(SMLoc::getFromPointer(Str.data()), 59381e5cd9eSAdrian Prantl SourceMgr::DK_Error, 59481e5cd9eSAdrian Prantl "missing closing \"]\" for regex variable"); 59581e5cd9eSAdrian Prantl exit(1); 59681e5cd9eSAdrian Prantl } 597061d2baaSEli Bendersky BracketDepth--; 598061d2baaSEli Bendersky break; 599061d2baaSEli Bendersky } 600061d2baaSEli Bendersky Str = Str.substr(1); 601061d2baaSEli Bendersky Offset++; 602061d2baaSEli Bendersky } 603061d2baaSEli Bendersky } 604061d2baaSEli Bendersky 605061d2baaSEli Bendersky return StringRef::npos; 606061d2baaSEli Bendersky } 607061d2baaSEli Bendersky 608061d2baaSEli Bendersky 60974d50731SChris Lattner //===----------------------------------------------------------------------===// 61074d50731SChris Lattner // Check Strings. 61174d50731SChris Lattner //===----------------------------------------------------------------------===// 6123b40b445SChris Lattner 6133b40b445SChris Lattner /// CheckString - This is a check that we found in the input file. 6143b40b445SChris Lattner struct CheckString { 6153b40b445SChris Lattner /// Pat - The pattern to match. 6163b40b445SChris Lattner Pattern Pat; 61726cccfe1SChris Lattner 61813df4626SMatt Arsenault /// Prefix - Which prefix name this check matched. 61913df4626SMatt Arsenault StringRef Prefix; 62013df4626SMatt Arsenault 62126cccfe1SChris Lattner /// Loc - The location in the match file that the check string was specified. 62226cccfe1SChris Lattner SMLoc Loc; 62326cccfe1SChris Lattner 62438820972SMatt Arsenault /// CheckTy - Specify what kind of check this is. e.g. CHECK-NEXT: directive, 62538820972SMatt Arsenault /// as opposed to a CHECK: directive. 62685913ccaSJames Y Knight // Check::CheckType CheckTy; 627f8bd2e5bSStephen Lin 62891a1b2c9SMichael Liao /// DagNotStrings - These are all of the strings that are disallowed from 629236d2d5eSChris Lattner /// occurring between this match string and the previous one (or start of 630236d2d5eSChris Lattner /// file). 63191a1b2c9SMichael Liao std::vector<Pattern> DagNotStrings; 632236d2d5eSChris Lattner 63385913ccaSJames Y Knight CheckString(const Pattern &P, StringRef S, SMLoc L) 63485913ccaSJames Y Knight : Pat(P), Prefix(S), Loc(L) {} 635dcc7d48dSMichael Liao 63691a1b2c9SMichael Liao /// Check - Match check string and its "not strings" and/or "dag strings". 637e93a3a08SStephen Lin size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, 638f8bd2e5bSStephen Lin size_t &MatchLen, StringMap<StringRef> &VariableTable) const; 639dcc7d48dSMichael Liao 640dcc7d48dSMichael Liao /// CheckNext - Verify there is a single line in the given buffer. 641dcc7d48dSMichael Liao bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; 642dcc7d48dSMichael Liao 64301ac1707SDuncan P. N. Exon Smith /// CheckSame - Verify there is no newline in the given buffer. 64401ac1707SDuncan P. N. Exon Smith bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; 64501ac1707SDuncan P. N. Exon Smith 646dcc7d48dSMichael Liao /// CheckNot - Verify there's no "not strings" in the given buffer. 647dcc7d48dSMichael Liao bool CheckNot(const SourceMgr &SM, StringRef Buffer, 64891a1b2c9SMichael Liao const std::vector<const Pattern *> &NotStrings, 64991a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) const; 65091a1b2c9SMichael Liao 65191a1b2c9SMichael Liao /// CheckDag - Match "dag strings" and their mixed "not strings". 65291a1b2c9SMichael Liao size_t CheckDag(const SourceMgr &SM, StringRef Buffer, 65391a1b2c9SMichael Liao std::vector<const Pattern *> &NotStrings, 654dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const; 65526cccfe1SChris Lattner }; 65626cccfe1SChris Lattner 6575ea04c38SGuy Benyei /// Canonicalize whitespaces in the input file. Line endings are replaced 6585ea04c38SGuy Benyei /// with UNIX-style '\n'. 6595ea04c38SGuy Benyei /// 6605ea04c38SGuy Benyei /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace 6615ea04c38SGuy Benyei /// characters to a single space. 6621961f14cSDavid Blaikie static std::unique_ptr<MemoryBuffer> 6631961f14cSDavid Blaikie CanonicalizeInputFile(std::unique_ptr<MemoryBuffer> MB, 6645ea04c38SGuy Benyei bool PreserveHorizontal) { 6650e45d24aSChris Lattner SmallString<128> NewFile; 666a2f8fc5aSChris Lattner NewFile.reserve(MB->getBufferSize()); 667a2f8fc5aSChris Lattner 668a2f8fc5aSChris Lattner for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd(); 669a2f8fc5aSChris Lattner Ptr != End; ++Ptr) { 670fd781bf0SNAKAMURA Takumi // Eliminate trailing dosish \r. 671fd781bf0SNAKAMURA Takumi if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { 672fd781bf0SNAKAMURA Takumi continue; 673fd781bf0SNAKAMURA Takumi } 674fd781bf0SNAKAMURA Takumi 6755ea04c38SGuy Benyei // If current char is not a horizontal whitespace or if horizontal 6765ea04c38SGuy Benyei // whitespace canonicalization is disabled, dump it to output as is. 6775ea04c38SGuy Benyei if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) { 678a2f8fc5aSChris Lattner NewFile.push_back(*Ptr); 679a2f8fc5aSChris Lattner continue; 680a2f8fc5aSChris Lattner } 681a2f8fc5aSChris Lattner 682a2f8fc5aSChris Lattner // Otherwise, add one space and advance over neighboring space. 683a2f8fc5aSChris Lattner NewFile.push_back(' '); 684a2f8fc5aSChris Lattner while (Ptr+1 != End && 685a2f8fc5aSChris Lattner (Ptr[1] == ' ' || Ptr[1] == '\t')) 686a2f8fc5aSChris Lattner ++Ptr; 687a2f8fc5aSChris Lattner } 688a2f8fc5aSChris Lattner 6891961f14cSDavid Blaikie return std::unique_ptr<MemoryBuffer>( 6901961f14cSDavid Blaikie MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier())); 691a2f8fc5aSChris Lattner } 692a2f8fc5aSChris Lattner 69338820972SMatt Arsenault static bool IsPartOfWord(char c) { 69438820972SMatt Arsenault return (isalnum(c) || c == '-' || c == '_'); 69538820972SMatt Arsenault } 69638820972SMatt Arsenault 69713df4626SMatt Arsenault // Get the size of the prefix extension. 69813df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) { 69913df4626SMatt Arsenault switch (Ty) { 70013df4626SMatt Arsenault case Check::CheckNone: 701a908e7bdSPaul Robinson case Check::CheckBadNot: 70213df4626SMatt Arsenault return 0; 70313df4626SMatt Arsenault 70413df4626SMatt Arsenault case Check::CheckPlain: 70513df4626SMatt Arsenault return sizeof(":") - 1; 70613df4626SMatt Arsenault 70713df4626SMatt Arsenault case Check::CheckNext: 70813df4626SMatt Arsenault return sizeof("-NEXT:") - 1; 70913df4626SMatt Arsenault 71001ac1707SDuncan P. N. Exon Smith case Check::CheckSame: 71101ac1707SDuncan P. N. Exon Smith return sizeof("-SAME:") - 1; 71201ac1707SDuncan P. N. Exon Smith 71313df4626SMatt Arsenault case Check::CheckNot: 71413df4626SMatt Arsenault return sizeof("-NOT:") - 1; 71513df4626SMatt Arsenault 71613df4626SMatt Arsenault case Check::CheckDAG: 71713df4626SMatt Arsenault return sizeof("-DAG:") - 1; 71813df4626SMatt Arsenault 71913df4626SMatt Arsenault case Check::CheckLabel: 72013df4626SMatt Arsenault return sizeof("-LABEL:") - 1; 72113df4626SMatt Arsenault 72213df4626SMatt Arsenault case Check::CheckEOF: 72313df4626SMatt Arsenault llvm_unreachable("Should not be using EOF size"); 72413df4626SMatt Arsenault } 72513df4626SMatt Arsenault 72613df4626SMatt Arsenault llvm_unreachable("Bad check type"); 72713df4626SMatt Arsenault } 72813df4626SMatt Arsenault 72913df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) { 730c4d2d471SMatt Arsenault char NextChar = Buffer[Prefix.size()]; 73138820972SMatt Arsenault 73238820972SMatt Arsenault // Verify that the : is present after the prefix. 73313df4626SMatt Arsenault if (NextChar == ':') 73438820972SMatt Arsenault return Check::CheckPlain; 73538820972SMatt Arsenault 73613df4626SMatt Arsenault if (NextChar != '-') 73738820972SMatt Arsenault return Check::CheckNone; 73838820972SMatt Arsenault 739c4d2d471SMatt Arsenault StringRef Rest = Buffer.drop_front(Prefix.size() + 1); 74013df4626SMatt Arsenault if (Rest.startswith("NEXT:")) 74138820972SMatt Arsenault return Check::CheckNext; 74238820972SMatt Arsenault 74301ac1707SDuncan P. N. Exon Smith if (Rest.startswith("SAME:")) 74401ac1707SDuncan P. N. Exon Smith return Check::CheckSame; 74501ac1707SDuncan P. N. Exon Smith 74613df4626SMatt Arsenault if (Rest.startswith("NOT:")) 74738820972SMatt Arsenault return Check::CheckNot; 74838820972SMatt Arsenault 74913df4626SMatt Arsenault if (Rest.startswith("DAG:")) 75038820972SMatt Arsenault return Check::CheckDAG; 75138820972SMatt Arsenault 75213df4626SMatt Arsenault if (Rest.startswith("LABEL:")) 75338820972SMatt Arsenault return Check::CheckLabel; 75413df4626SMatt Arsenault 755a908e7bdSPaul Robinson // You can't combine -NOT with another suffix. 756a908e7bdSPaul Robinson if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") || 757a908e7bdSPaul Robinson Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") || 758a908e7bdSPaul Robinson Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:")) 759a908e7bdSPaul Robinson return Check::CheckBadNot; 760a908e7bdSPaul Robinson 76113df4626SMatt Arsenault return Check::CheckNone; 76238820972SMatt Arsenault } 76338820972SMatt Arsenault 76413df4626SMatt Arsenault // From the given position, find the next character after the word. 76513df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) { 76613df4626SMatt Arsenault while (Loc < Str.size() && IsPartOfWord(Str[Loc])) 76713df4626SMatt Arsenault ++Loc; 76813df4626SMatt Arsenault return Loc; 76913df4626SMatt Arsenault } 77013df4626SMatt Arsenault 77113df4626SMatt Arsenault // Try to find the first match in buffer for any prefix. If a valid match is 77213df4626SMatt Arsenault // found, return that prefix and set its type and location. If there are almost 77313df4626SMatt Arsenault // matches (e.g. the actual prefix string is found, but is not an actual check 77413df4626SMatt Arsenault // string), but no valid match, return an empty string and set the position to 77513df4626SMatt Arsenault // resume searching from. If no partial matches are found, return an empty 77613df4626SMatt Arsenault // string and the location will be StringRef::npos. If one prefix is a substring 77713df4626SMatt Arsenault // of another, the maximal match should be found. e.g. if "A" and "AA" are 77813df4626SMatt Arsenault // prefixes then AA-CHECK: should match the second one. 77913df4626SMatt Arsenault static StringRef FindFirstCandidateMatch(StringRef &Buffer, 78013df4626SMatt Arsenault Check::CheckType &CheckTy, 78113df4626SMatt Arsenault size_t &CheckLoc) { 78213df4626SMatt Arsenault StringRef FirstPrefix; 78313df4626SMatt Arsenault size_t FirstLoc = StringRef::npos; 78413df4626SMatt Arsenault size_t SearchLoc = StringRef::npos; 78513df4626SMatt Arsenault Check::CheckType FirstTy = Check::CheckNone; 78613df4626SMatt Arsenault 78713df4626SMatt Arsenault CheckTy = Check::CheckNone; 78813df4626SMatt Arsenault CheckLoc = StringRef::npos; 78913df4626SMatt Arsenault 7908f870499SBenjamin Kramer for (StringRef Prefix : CheckPrefixes) { 79113df4626SMatt Arsenault size_t PrefixLoc = Buffer.find(Prefix); 79213df4626SMatt Arsenault 79313df4626SMatt Arsenault if (PrefixLoc == StringRef::npos) 79413df4626SMatt Arsenault continue; 79513df4626SMatt Arsenault 79613df4626SMatt Arsenault // Track where we are searching for invalid prefixes that look almost right. 79713df4626SMatt Arsenault // We need to only advance to the first partial match on the next attempt 79813df4626SMatt Arsenault // since a partial match could be a substring of a later, valid prefix. 79913df4626SMatt Arsenault // Need to skip to the end of the word, otherwise we could end up 80013df4626SMatt Arsenault // matching a prefix in a substring later. 80113df4626SMatt Arsenault if (PrefixLoc < SearchLoc) 80213df4626SMatt Arsenault SearchLoc = SkipWord(Buffer, PrefixLoc); 80313df4626SMatt Arsenault 80413df4626SMatt Arsenault // We only want to find the first match to avoid skipping some. 80513df4626SMatt Arsenault if (PrefixLoc > FirstLoc) 80613df4626SMatt Arsenault continue; 807a7181a1bSAlexey Samsonov // If one matching check-prefix is a prefix of another, choose the 808a7181a1bSAlexey Samsonov // longer one. 809a7181a1bSAlexey Samsonov if (PrefixLoc == FirstLoc && Prefix.size() < FirstPrefix.size()) 810a7181a1bSAlexey Samsonov continue; 81113df4626SMatt Arsenault 81213df4626SMatt Arsenault StringRef Rest = Buffer.drop_front(PrefixLoc); 81313df4626SMatt Arsenault // Make sure we have actually found the prefix, and not a word containing 81413df4626SMatt Arsenault // it. This should also prevent matching the wrong prefix when one is a 81513df4626SMatt Arsenault // substring of another. 81613df4626SMatt Arsenault if (PrefixLoc != 0 && IsPartOfWord(Buffer[PrefixLoc - 1])) 81743b5f572SDaniel Sanders FirstTy = Check::CheckNone; 81843b5f572SDaniel Sanders else 81943b5f572SDaniel Sanders FirstTy = FindCheckType(Rest, Prefix); 82013df4626SMatt Arsenault 82113df4626SMatt Arsenault FirstLoc = PrefixLoc; 822a7181a1bSAlexey Samsonov FirstPrefix = Prefix; 82313df4626SMatt Arsenault } 82413df4626SMatt Arsenault 825a7181a1bSAlexey Samsonov // If the first prefix is invalid, we should continue the search after it. 826a7181a1bSAlexey Samsonov if (FirstTy == Check::CheckNone) { 82713df4626SMatt Arsenault CheckLoc = SearchLoc; 828a7181a1bSAlexey Samsonov return ""; 829a7181a1bSAlexey Samsonov } 830a7181a1bSAlexey Samsonov 83113df4626SMatt Arsenault CheckTy = FirstTy; 83213df4626SMatt Arsenault CheckLoc = FirstLoc; 83313df4626SMatt Arsenault return FirstPrefix; 83413df4626SMatt Arsenault } 83513df4626SMatt Arsenault 83613df4626SMatt Arsenault static StringRef FindFirstMatchingPrefix(StringRef &Buffer, 83713df4626SMatt Arsenault unsigned &LineNumber, 83813df4626SMatt Arsenault Check::CheckType &CheckTy, 83913df4626SMatt Arsenault size_t &CheckLoc) { 84013df4626SMatt Arsenault while (!Buffer.empty()) { 84113df4626SMatt Arsenault StringRef Prefix = FindFirstCandidateMatch(Buffer, CheckTy, CheckLoc); 84213df4626SMatt Arsenault // If we found a real match, we are done. 84313df4626SMatt Arsenault if (!Prefix.empty()) { 84413df4626SMatt Arsenault LineNumber += Buffer.substr(0, CheckLoc).count('\n'); 84513df4626SMatt Arsenault return Prefix; 84613df4626SMatt Arsenault } 84713df4626SMatt Arsenault 84813df4626SMatt Arsenault // We didn't find any almost matches either, we are also done. 84913df4626SMatt Arsenault if (CheckLoc == StringRef::npos) 85013df4626SMatt Arsenault return StringRef(); 85113df4626SMatt Arsenault 85213df4626SMatt Arsenault LineNumber += Buffer.substr(0, CheckLoc + 1).count('\n'); 85313df4626SMatt Arsenault 85413df4626SMatt Arsenault // Advance to the last possible match we found and try again. 85513df4626SMatt Arsenault Buffer = Buffer.drop_front(CheckLoc + 1); 85613df4626SMatt Arsenault } 85713df4626SMatt Arsenault 85813df4626SMatt Arsenault return StringRef(); 85938820972SMatt Arsenault } 860ee3c74fbSChris Lattner 861ee3c74fbSChris Lattner /// ReadCheckFile - Read the check file, which specifies the sequence of 862ee3c74fbSChris Lattner /// expected strings. The strings are added to the CheckStrings vector. 86343d50d4aSEli Bendersky /// Returns true in case of an error, false otherwise. 864ee3c74fbSChris Lattner static bool ReadCheckFile(SourceMgr &SM, 86526cccfe1SChris Lattner std::vector<CheckString> &CheckStrings) { 866adf21f2aSRafael Espindola ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 867adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(CheckFilename); 868adf21f2aSRafael Espindola if (std::error_code EC = FileOrErr.getError()) { 869adf21f2aSRafael Espindola errs() << "Could not open check file '" << CheckFilename 870adf21f2aSRafael Espindola << "': " << EC.message() << '\n'; 871ee3c74fbSChris Lattner return true; 872ee3c74fbSChris Lattner } 873a2f8fc5aSChris Lattner 874a2f8fc5aSChris Lattner // If we want to canonicalize whitespace, strip excess whitespace from the 8755ea04c38SGuy Benyei // buffer containing the CHECK lines. Remove DOS style line endings. 8763560ff2cSRafael Espindola std::unique_ptr<MemoryBuffer> F = CanonicalizeInputFile( 8773560ff2cSRafael Espindola std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace); 878ee3c74fbSChris Lattner 87910f10cedSChris Lattner // Find all instances of CheckPrefix followed by : in the file. 880caa5fc0cSChris Lattner StringRef Buffer = F->getBuffer(); 88156ccdbbdSAlexander Kornienko 8821961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(F), SMLoc()); 8831961f14cSDavid Blaikie 88456ccdbbdSAlexander Kornienko std::vector<Pattern> ImplicitNegativeChecks; 88556ccdbbdSAlexander Kornienko for (const auto &PatternString : ImplicitCheckNot) { 88656ccdbbdSAlexander Kornienko // Create a buffer with fake command line content in order to display the 88756ccdbbdSAlexander Kornienko // command line option responsible for the specific implicit CHECK-NOT. 888ff43d69dSDavid Blaikie std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str(); 88956ccdbbdSAlexander Kornienko std::string Suffix = "'"; 8903560ff2cSRafael Espindola std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy( 8913560ff2cSRafael Espindola Prefix + PatternString + Suffix, "command line"); 8923560ff2cSRafael Espindola 89356ccdbbdSAlexander Kornienko StringRef PatternInBuffer = 89456ccdbbdSAlexander Kornienko CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); 8951961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); 89656ccdbbdSAlexander Kornienko 89756ccdbbdSAlexander Kornienko ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); 89856ccdbbdSAlexander Kornienko ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, 89956ccdbbdSAlexander Kornienko "IMPLICIT-CHECK", SM, 0); 90056ccdbbdSAlexander Kornienko } 90156ccdbbdSAlexander Kornienko 90256ccdbbdSAlexander Kornienko 90356ccdbbdSAlexander Kornienko std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks; 904236d2d5eSChris Lattner 90543d50d4aSEli Bendersky // LineNumber keeps track of the line on which CheckPrefix instances are 90643d50d4aSEli Bendersky // found. 90792987fb3SAlexander Kornienko unsigned LineNumber = 1; 90892987fb3SAlexander Kornienko 909ee3c74fbSChris Lattner while (1) { 91013df4626SMatt Arsenault Check::CheckType CheckTy; 91113df4626SMatt Arsenault size_t PrefixLoc; 91213df4626SMatt Arsenault 91313df4626SMatt Arsenault // See if a prefix occurs in the memory buffer. 91413df4626SMatt Arsenault StringRef UsedPrefix = FindFirstMatchingPrefix(Buffer, 91513df4626SMatt Arsenault LineNumber, 91613df4626SMatt Arsenault CheckTy, 91713df4626SMatt Arsenault PrefixLoc); 91813df4626SMatt Arsenault if (UsedPrefix.empty()) 919ee3c74fbSChris Lattner break; 920ee3c74fbSChris Lattner 92113df4626SMatt Arsenault Buffer = Buffer.drop_front(PrefixLoc); 92292987fb3SAlexander Kornienko 92313df4626SMatt Arsenault // Location to use for error messages. 92413df4626SMatt Arsenault const char *UsedPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1); 92592987fb3SAlexander Kornienko 92613df4626SMatt Arsenault // PrefixLoc is to the start of the prefix. Skip to the end. 92713df4626SMatt Arsenault Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy)); 92810f10cedSChris Lattner 929a908e7bdSPaul Robinson // Complain about useful-looking but unsupported suffixes. 930a908e7bdSPaul Robinson if (CheckTy == Check::CheckBadNot) { 931a908e7bdSPaul Robinson SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), 932a908e7bdSPaul Robinson SourceMgr::DK_Error, 933a908e7bdSPaul Robinson "unsupported -NOT combo on prefix '" + UsedPrefix + "'"); 934a908e7bdSPaul Robinson return true; 935a908e7bdSPaul Robinson } 936a908e7bdSPaul Robinson 93738820972SMatt Arsenault // Okay, we found the prefix, yay. Remember the rest of the line, but ignore 93838820972SMatt Arsenault // leading and trailing whitespace. 939236d2d5eSChris Lattner Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); 940ee3c74fbSChris Lattner 941ee3c74fbSChris Lattner // Scan ahead to the end of line. 942caa5fc0cSChris Lattner size_t EOL = Buffer.find_first_of("\n\r"); 943ee3c74fbSChris Lattner 944838fb09aSDan Gohman // Remember the location of the start of the pattern, for diagnostics. 945838fb09aSDan Gohman SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); 946838fb09aSDan Gohman 94774d50731SChris Lattner // Parse the pattern. 94838820972SMatt Arsenault Pattern P(CheckTy); 94913df4626SMatt Arsenault if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber)) 950ee3c74fbSChris Lattner return true; 951ee3c74fbSChris Lattner 952f8bd2e5bSStephen Lin // Verify that CHECK-LABEL lines do not define or use variables 95338820972SMatt Arsenault if ((CheckTy == Check::CheckLabel) && P.hasVariable()) { 95413df4626SMatt Arsenault SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 955f8bd2e5bSStephen Lin SourceMgr::DK_Error, 95613df4626SMatt Arsenault "found '" + UsedPrefix + "-LABEL:'" 95713df4626SMatt Arsenault " with variable definition or use"); 958f8bd2e5bSStephen Lin return true; 959f8bd2e5bSStephen Lin } 960f8bd2e5bSStephen Lin 961236d2d5eSChris Lattner Buffer = Buffer.substr(EOL); 96274d50731SChris Lattner 963da108b4eSChris Lattner // Verify that CHECK-NEXT lines have at least one CHECK line before them. 96401ac1707SDuncan P. N. Exon Smith if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) && 96501ac1707SDuncan P. N. Exon Smith CheckStrings.empty()) { 96601ac1707SDuncan P. N. Exon Smith StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME"; 96713df4626SMatt Arsenault SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 96803b80a40SChris Lattner SourceMgr::DK_Error, 96901ac1707SDuncan P. N. Exon Smith "found '" + UsedPrefix + "-" + Type + "' without previous '" 97013df4626SMatt Arsenault + UsedPrefix + ": line"); 971da108b4eSChris Lattner return true; 972da108b4eSChris Lattner } 973da108b4eSChris Lattner 97491a1b2c9SMichael Liao // Handle CHECK-DAG/-NOT. 97538820972SMatt Arsenault if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) { 97691a1b2c9SMichael Liao DagNotMatches.push_back(P); 97774d50731SChris Lattner continue; 97874d50731SChris Lattner } 97974d50731SChris Lattner 980ee3c74fbSChris Lattner // Okay, add the string we captured to the output vector and move on. 98185913ccaSJames Y Knight CheckStrings.emplace_back(P, UsedPrefix, PatternLoc); 98291a1b2c9SMichael Liao std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 98356ccdbbdSAlexander Kornienko DagNotMatches = ImplicitNegativeChecks; 984ee3c74fbSChris Lattner } 985ee3c74fbSChris Lattner 98613df4626SMatt Arsenault // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first 98713df4626SMatt Arsenault // prefix as a filler for the error message. 98891a1b2c9SMichael Liao if (!DagNotMatches.empty()) { 989f5e2fc47SBenjamin Kramer CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(), 99085913ccaSJames Y Knight SMLoc::getFromPointer(Buffer.data())); 99191a1b2c9SMichael Liao std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 992eba55822SJakob Stoklund Olesen } 993eba55822SJakob Stoklund Olesen 994ee3c74fbSChris Lattner if (CheckStrings.empty()) { 99513df4626SMatt Arsenault errs() << "error: no check strings found with prefix" 99613df4626SMatt Arsenault << (CheckPrefixes.size() > 1 ? "es " : " "); 9973e3ef2f2SChris Bieneman prefix_iterator I = CheckPrefixes.begin(); 9983e3ef2f2SChris Bieneman prefix_iterator E = CheckPrefixes.end(); 9993e3ef2f2SChris Bieneman if (I != E) { 10003e3ef2f2SChris Bieneman errs() << "\'" << *I << ":'"; 10013e3ef2f2SChris Bieneman ++I; 100213df4626SMatt Arsenault } 10033e3ef2f2SChris Bieneman for (; I != E; ++I) 10043e3ef2f2SChris Bieneman errs() << ", \'" << *I << ":'"; 100513df4626SMatt Arsenault 100613df4626SMatt Arsenault errs() << '\n'; 1007ee3c74fbSChris Lattner return true; 1008ee3c74fbSChris Lattner } 1009ee3c74fbSChris Lattner 1010ee3c74fbSChris Lattner return false; 1011ee3c74fbSChris Lattner } 1012ee3c74fbSChris Lattner 10133c76c523SCraig Topper static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, 101491a1b2c9SMichael Liao const Pattern &Pat, StringRef Buffer, 1015e0ef65abSDaniel Dunbar StringMap<StringRef> &VariableTable) { 1016da108b4eSChris Lattner // Otherwise, we have an error, emit an error message. 101791a1b2c9SMichael Liao SM.PrintMessage(Loc, SourceMgr::DK_Error, 101803b80a40SChris Lattner "expected string not found in input"); 1019da108b4eSChris Lattner 1020da108b4eSChris Lattner // Print the "scanning from here" line. If the current position is at the 1021da108b4eSChris Lattner // end of a line, advance to the start of the next line. 1022caa5fc0cSChris Lattner Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r")); 1023da108b4eSChris Lattner 102403b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 102503b80a40SChris Lattner "scanning from here"); 1026e0ef65abSDaniel Dunbar 1027e0ef65abSDaniel Dunbar // Allow the pattern to print additional information if desired. 102891a1b2c9SMichael Liao Pat.PrintFailureInfo(SM, Buffer, VariableTable); 102991a1b2c9SMichael Liao } 103091a1b2c9SMichael Liao 103191a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, 103291a1b2c9SMichael Liao StringRef Buffer, 103391a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) { 103491a1b2c9SMichael Liao PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable); 1035da108b4eSChris Lattner } 1036da108b4eSChris Lattner 103737183584SChris Lattner /// CountNumNewlinesBetween - Count the number of newlines in the specified 103837183584SChris Lattner /// range. 1039592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range, 1040592fe880SRichard Smith const char *&FirstNewLine) { 1041da108b4eSChris Lattner unsigned NumNewLines = 0; 104237183584SChris Lattner while (1) { 1043da108b4eSChris Lattner // Scan for newline. 104437183584SChris Lattner Range = Range.substr(Range.find_first_of("\n\r")); 104537183584SChris Lattner if (Range.empty()) return NumNewLines; 1046da108b4eSChris Lattner 1047da108b4eSChris Lattner ++NumNewLines; 1048da108b4eSChris Lattner 1049da108b4eSChris Lattner // Handle \n\r and \r\n as a single newline. 105037183584SChris Lattner if (Range.size() > 1 && 105137183584SChris Lattner (Range[1] == '\n' || Range[1] == '\r') && 105237183584SChris Lattner (Range[0] != Range[1])) 105337183584SChris Lattner Range = Range.substr(1); 105437183584SChris Lattner Range = Range.substr(1); 1055592fe880SRichard Smith 1056592fe880SRichard Smith if (NumNewLines == 1) 1057592fe880SRichard Smith FirstNewLine = Range.begin(); 1058da108b4eSChris Lattner } 1059da108b4eSChris Lattner } 1060da108b4eSChris Lattner 1061dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, 1062e93a3a08SStephen Lin bool IsLabelScanMode, size_t &MatchLen, 1063dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const { 106491a1b2c9SMichael Liao size_t LastPos = 0; 106591a1b2c9SMichael Liao std::vector<const Pattern *> NotStrings; 106691a1b2c9SMichael Liao 1067e93a3a08SStephen Lin // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL 1068e93a3a08SStephen Lin // bounds; we have not processed variable definitions within the bounded block 1069e93a3a08SStephen Lin // yet so cannot handle any final CHECK-DAG yet; this is handled when going 1070e93a3a08SStephen Lin // over the block again (including the last CHECK-LABEL) in normal mode. 1071e93a3a08SStephen Lin if (!IsLabelScanMode) { 107291a1b2c9SMichael Liao // Match "dag strings" (with mixed "not strings" if any). 107391a1b2c9SMichael Liao LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable); 107491a1b2c9SMichael Liao if (LastPos == StringRef::npos) 107591a1b2c9SMichael Liao return StringRef::npos; 1076e93a3a08SStephen Lin } 107791a1b2c9SMichael Liao 107891a1b2c9SMichael Liao // Match itself from the last position after matching CHECK-DAG. 107991a1b2c9SMichael Liao StringRef MatchBuffer = Buffer.substr(LastPos); 108091a1b2c9SMichael Liao size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); 1081dcc7d48dSMichael Liao if (MatchPos == StringRef::npos) { 108291a1b2c9SMichael Liao PrintCheckFailed(SM, *this, MatchBuffer, VariableTable); 1083dcc7d48dSMichael Liao return StringRef::npos; 1084dcc7d48dSMichael Liao } 1085dcc7d48dSMichael Liao 1086e93a3a08SStephen Lin // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT 1087e93a3a08SStephen Lin // or CHECK-NOT 1088e93a3a08SStephen Lin if (!IsLabelScanMode) { 108991a1b2c9SMichael Liao StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 1090dcc7d48dSMichael Liao 1091dcc7d48dSMichael Liao // If this check is a "CHECK-NEXT", verify that the previous match was on 1092dcc7d48dSMichael Liao // the previous line (i.e. that there is one newline between them). 1093dcc7d48dSMichael Liao if (CheckNext(SM, SkippedRegion)) 1094dcc7d48dSMichael Liao return StringRef::npos; 1095dcc7d48dSMichael Liao 109601ac1707SDuncan P. N. Exon Smith // If this check is a "CHECK-SAME", verify that the previous match was on 109701ac1707SDuncan P. N. Exon Smith // the same line (i.e. that there is no newline between them). 109801ac1707SDuncan P. N. Exon Smith if (CheckSame(SM, SkippedRegion)) 109901ac1707SDuncan P. N. Exon Smith return StringRef::npos; 110001ac1707SDuncan P. N. Exon Smith 1101dcc7d48dSMichael Liao // If this match had "not strings", verify that they don't exist in the 1102dcc7d48dSMichael Liao // skipped region. 110391a1b2c9SMichael Liao if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) 1104dcc7d48dSMichael Liao return StringRef::npos; 1105f8bd2e5bSStephen Lin } 1106dcc7d48dSMichael Liao 11077dfb92b9SMehdi Amini return LastPos + MatchPos; 1108dcc7d48dSMichael Liao } 1109dcc7d48dSMichael Liao 1110dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { 111185913ccaSJames Y Knight if (Pat.getCheckTy() != Check::CheckNext) 1112dcc7d48dSMichael Liao return false; 1113dcc7d48dSMichael Liao 1114dcc7d48dSMichael Liao // Count the number of newlines between the previous match and this one. 1115dcc7d48dSMichael Liao assert(Buffer.data() != 1116dcc7d48dSMichael Liao SM.getMemoryBuffer( 1117dcc7d48dSMichael Liao SM.FindBufferContainingLoc( 1118dcc7d48dSMichael Liao SMLoc::getFromPointer(Buffer.data())))->getBufferStart() && 1119dcc7d48dSMichael Liao "CHECK-NEXT can't be the first check in a file"); 1120dcc7d48dSMichael Liao 112166f09ad0SCraig Topper const char *FirstNewLine = nullptr; 1122592fe880SRichard Smith unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 1123dcc7d48dSMichael Liao 1124dcc7d48dSMichael Liao if (NumNewLines == 0) { 112513df4626SMatt Arsenault SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + 1126dcc7d48dSMichael Liao "-NEXT: is on the same line as previous match"); 1127dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), 1128dcc7d48dSMichael Liao SourceMgr::DK_Note, "'next' match was here"); 1129dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1130dcc7d48dSMichael Liao "previous match ended here"); 1131dcc7d48dSMichael Liao return true; 1132dcc7d48dSMichael Liao } 1133dcc7d48dSMichael Liao 1134dcc7d48dSMichael Liao if (NumNewLines != 1) { 113513df4626SMatt Arsenault SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + 1136dcc7d48dSMichael Liao "-NEXT: is not on the line after the previous match"); 1137dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), 1138dcc7d48dSMichael Liao SourceMgr::DK_Note, "'next' match was here"); 1139dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1140dcc7d48dSMichael Liao "previous match ended here"); 1141592fe880SRichard Smith SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, 1142592fe880SRichard Smith "non-matching line after previous match is here"); 1143dcc7d48dSMichael Liao return true; 1144dcc7d48dSMichael Liao } 1145dcc7d48dSMichael Liao 1146dcc7d48dSMichael Liao return false; 1147dcc7d48dSMichael Liao } 1148dcc7d48dSMichael Liao 114901ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { 115085913ccaSJames Y Knight if (Pat.getCheckTy() != Check::CheckSame) 115101ac1707SDuncan P. N. Exon Smith return false; 115201ac1707SDuncan P. N. Exon Smith 115301ac1707SDuncan P. N. Exon Smith // Count the number of newlines between the previous match and this one. 115401ac1707SDuncan P. N. Exon Smith assert(Buffer.data() != 115501ac1707SDuncan P. N. Exon Smith SM.getMemoryBuffer(SM.FindBufferContainingLoc( 115601ac1707SDuncan P. N. Exon Smith SMLoc::getFromPointer(Buffer.data()))) 115701ac1707SDuncan P. N. Exon Smith ->getBufferStart() && 115801ac1707SDuncan P. N. Exon Smith "CHECK-SAME can't be the first check in a file"); 115901ac1707SDuncan P. N. Exon Smith 116001ac1707SDuncan P. N. Exon Smith const char *FirstNewLine = nullptr; 116101ac1707SDuncan P. N. Exon Smith unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 116201ac1707SDuncan P. N. Exon Smith 116301ac1707SDuncan P. N. Exon Smith if (NumNewLines != 0) { 116401ac1707SDuncan P. N. Exon Smith SM.PrintMessage(Loc, SourceMgr::DK_Error, 116501ac1707SDuncan P. N. Exon Smith Prefix + 116601ac1707SDuncan P. N. Exon Smith "-SAME: is not on the same line as the previous match"); 116701ac1707SDuncan P. N. Exon Smith SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 116801ac1707SDuncan P. N. Exon Smith "'next' match was here"); 116901ac1707SDuncan P. N. Exon Smith SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 117001ac1707SDuncan P. N. Exon Smith "previous match ended here"); 117101ac1707SDuncan P. N. Exon Smith return true; 117201ac1707SDuncan P. N. Exon Smith } 117301ac1707SDuncan P. N. Exon Smith 117401ac1707SDuncan P. N. Exon Smith return false; 117501ac1707SDuncan P. N. Exon Smith } 117601ac1707SDuncan P. N. Exon Smith 1177dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer, 117891a1b2c9SMichael Liao const std::vector<const Pattern *> &NotStrings, 1179dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const { 11808f870499SBenjamin Kramer for (const Pattern *Pat : NotStrings) { 118138820972SMatt Arsenault assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!"); 118291a1b2c9SMichael Liao 1183dcc7d48dSMichael Liao size_t MatchLen = 0; 118491a1b2c9SMichael Liao size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable); 1185dcc7d48dSMichael Liao 1186dcc7d48dSMichael Liao if (Pos == StringRef::npos) continue; 1187dcc7d48dSMichael Liao 1188dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos), 1189dcc7d48dSMichael Liao SourceMgr::DK_Error, 119013df4626SMatt Arsenault Prefix + "-NOT: string occurred!"); 119191a1b2c9SMichael Liao SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note, 119213df4626SMatt Arsenault Prefix + "-NOT: pattern specified here"); 1193dcc7d48dSMichael Liao return true; 1194dcc7d48dSMichael Liao } 1195dcc7d48dSMichael Liao 1196dcc7d48dSMichael Liao return false; 1197dcc7d48dSMichael Liao } 1198dcc7d48dSMichael Liao 119991a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, 120091a1b2c9SMichael Liao std::vector<const Pattern *> &NotStrings, 120191a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) const { 120291a1b2c9SMichael Liao if (DagNotStrings.empty()) 120391a1b2c9SMichael Liao return 0; 120491a1b2c9SMichael Liao 120591a1b2c9SMichael Liao size_t LastPos = 0; 120691a1b2c9SMichael Liao size_t StartPos = LastPos; 120791a1b2c9SMichael Liao 12088f870499SBenjamin Kramer for (const Pattern &Pat : DagNotStrings) { 120938820972SMatt Arsenault assert((Pat.getCheckTy() == Check::CheckDAG || 121038820972SMatt Arsenault Pat.getCheckTy() == Check::CheckNot) && 121191a1b2c9SMichael Liao "Invalid CHECK-DAG or CHECK-NOT!"); 121291a1b2c9SMichael Liao 121338820972SMatt Arsenault if (Pat.getCheckTy() == Check::CheckNot) { 121491a1b2c9SMichael Liao NotStrings.push_back(&Pat); 121591a1b2c9SMichael Liao continue; 121691a1b2c9SMichael Liao } 121791a1b2c9SMichael Liao 121838820972SMatt Arsenault assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!"); 121991a1b2c9SMichael Liao 122091a1b2c9SMichael Liao size_t MatchLen = 0, MatchPos; 122191a1b2c9SMichael Liao 122291a1b2c9SMichael Liao // CHECK-DAG always matches from the start. 122391a1b2c9SMichael Liao StringRef MatchBuffer = Buffer.substr(StartPos); 122491a1b2c9SMichael Liao MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); 122591a1b2c9SMichael Liao // With a group of CHECK-DAGs, a single mismatching means the match on 122691a1b2c9SMichael Liao // that group of CHECK-DAGs fails immediately. 122791a1b2c9SMichael Liao if (MatchPos == StringRef::npos) { 122891a1b2c9SMichael Liao PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable); 122991a1b2c9SMichael Liao return StringRef::npos; 123091a1b2c9SMichael Liao } 123191a1b2c9SMichael Liao // Re-calc it as the offset relative to the start of the original string. 123291a1b2c9SMichael Liao MatchPos += StartPos; 123391a1b2c9SMichael Liao 123491a1b2c9SMichael Liao if (!NotStrings.empty()) { 123591a1b2c9SMichael Liao if (MatchPos < LastPos) { 123691a1b2c9SMichael Liao // Reordered? 123791a1b2c9SMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos), 123891a1b2c9SMichael Liao SourceMgr::DK_Error, 123913df4626SMatt Arsenault Prefix + "-DAG: found a match of CHECK-DAG" 124091a1b2c9SMichael Liao " reordering across a CHECK-NOT"); 124191a1b2c9SMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos), 124291a1b2c9SMichael Liao SourceMgr::DK_Note, 124313df4626SMatt Arsenault Prefix + "-DAG: the farthest match of CHECK-DAG" 124491a1b2c9SMichael Liao " is found here"); 124591a1b2c9SMichael Liao SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note, 124613df4626SMatt Arsenault Prefix + "-NOT: the crossed pattern specified" 124791a1b2c9SMichael Liao " here"); 124891a1b2c9SMichael Liao SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note, 124913df4626SMatt Arsenault Prefix + "-DAG: the reordered pattern specified" 125091a1b2c9SMichael Liao " here"); 125191a1b2c9SMichael Liao return StringRef::npos; 125291a1b2c9SMichael Liao } 125391a1b2c9SMichael Liao // All subsequent CHECK-DAGs should be matched from the farthest 125491a1b2c9SMichael Liao // position of all precedent CHECK-DAGs (including this one.) 125591a1b2c9SMichael Liao StartPos = LastPos; 125691a1b2c9SMichael Liao // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to 125791a1b2c9SMichael Liao // CHECK-DAG, verify that there's no 'not' strings occurred in that 125891a1b2c9SMichael Liao // region. 125991a1b2c9SMichael Liao StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 1260cf708c32STim Northover if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) 126191a1b2c9SMichael Liao return StringRef::npos; 126291a1b2c9SMichael Liao // Clear "not strings". 126391a1b2c9SMichael Liao NotStrings.clear(); 126491a1b2c9SMichael Liao } 126591a1b2c9SMichael Liao 126691a1b2c9SMichael Liao // Update the last position with CHECK-DAG matches. 126791a1b2c9SMichael Liao LastPos = std::max(MatchPos + MatchLen, LastPos); 126891a1b2c9SMichael Liao } 126991a1b2c9SMichael Liao 127091a1b2c9SMichael Liao return LastPos; 127191a1b2c9SMichael Liao } 127291a1b2c9SMichael Liao 127313df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores. 127413df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) { 127513df4626SMatt Arsenault Regex Validator("^[a-zA-Z0-9_-]*$"); 127613df4626SMatt Arsenault return Validator.match(CheckPrefix); 127713df4626SMatt Arsenault } 127813df4626SMatt Arsenault 127913df4626SMatt Arsenault static bool ValidateCheckPrefixes() { 128013df4626SMatt Arsenault StringSet<> PrefixSet; 128113df4626SMatt Arsenault 12828f870499SBenjamin Kramer for (StringRef Prefix : CheckPrefixes) { 128324412b14SEli Bendersky // Reject empty prefixes. 128424412b14SEli Bendersky if (Prefix == "") 128524412b14SEli Bendersky return false; 128624412b14SEli Bendersky 12870356975cSDavid Blaikie if (!PrefixSet.insert(Prefix).second) 128813df4626SMatt Arsenault return false; 128913df4626SMatt Arsenault 129013df4626SMatt Arsenault if (!ValidateCheckPrefix(Prefix)) 129113df4626SMatt Arsenault return false; 129213df4626SMatt Arsenault } 129313df4626SMatt Arsenault 129413df4626SMatt Arsenault return true; 129513df4626SMatt Arsenault } 129613df4626SMatt Arsenault 129713df4626SMatt Arsenault // I don't think there's a way to specify an initial value for cl::list, 129813df4626SMatt Arsenault // so if nothing was specified, add the default 129913df4626SMatt Arsenault static void AddCheckPrefixIfNeeded() { 130013df4626SMatt Arsenault if (CheckPrefixes.empty()) 130113df4626SMatt Arsenault CheckPrefixes.push_back("CHECK"); 1302c2735158SRui Ueyama } 1303c2735158SRui Ueyama 13042bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) { 13052bd4f8b6SXinliang David Li errs() << "FileCheck command line: "; 13062bd4f8b6SXinliang David Li for (int I = 0; I < argc; I++) 13072bd4f8b6SXinliang David Li errs() << " " << argv[I]; 13082bd4f8b6SXinliang David Li errs() << "\n"; 13092bd4f8b6SXinliang David Li } 13102bd4f8b6SXinliang David Li 1311ee3c74fbSChris Lattner int main(int argc, char **argv) { 13122ad6d48bSRichard Smith sys::PrintStackTraceOnErrorSignal(argv[0]); 1313ee3c74fbSChris Lattner PrettyStackTraceProgram X(argc, argv); 1314ee3c74fbSChris Lattner cl::ParseCommandLineOptions(argc, argv); 1315ee3c74fbSChris Lattner 131613df4626SMatt Arsenault if (!ValidateCheckPrefixes()) { 131713df4626SMatt Arsenault errs() << "Supplied check-prefix is invalid! Prefixes must be unique and " 131813df4626SMatt Arsenault "start with a letter and contain only alphanumeric characters, " 131913df4626SMatt Arsenault "hyphens and underscores\n"; 1320c2735158SRui Ueyama return 2; 1321c2735158SRui Ueyama } 1322c2735158SRui Ueyama 132313df4626SMatt Arsenault AddCheckPrefixIfNeeded(); 132413df4626SMatt Arsenault 1325ee3c74fbSChris Lattner SourceMgr SM; 1326ee3c74fbSChris Lattner 1327ee3c74fbSChris Lattner // Read the expected strings from the check file. 132826cccfe1SChris Lattner std::vector<CheckString> CheckStrings; 1329ee3c74fbSChris Lattner if (ReadCheckFile(SM, CheckStrings)) 1330ee3c74fbSChris Lattner return 2; 1331ee3c74fbSChris Lattner 1332ee3c74fbSChris Lattner // Open the file to check and add it to SourceMgr. 1333adf21f2aSRafael Espindola ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 1334adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(InputFilename); 1335adf21f2aSRafael Espindola if (std::error_code EC = FileOrErr.getError()) { 1336adf21f2aSRafael Espindola errs() << "Could not open input file '" << InputFilename 1337adf21f2aSRafael Espindola << "': " << EC.message() << '\n'; 13388e1c6477SEli Bendersky return 2; 1339ee3c74fbSChris Lattner } 13403f6481d0SRafael Espindola std::unique_ptr<MemoryBuffer> &File = FileOrErr.get(); 13412c3e5cdfSChris Lattner 13421b9f936fSJustin Bogner if (File->getBufferSize() == 0 && !AllowEmptyInput) { 1343b692bed7SChris Lattner errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 13442bd4f8b6SXinliang David Li DumpCommandLine(argc, argv); 13458e1c6477SEli Bendersky return 2; 1346b692bed7SChris Lattner } 1347b692bed7SChris Lattner 13482c3e5cdfSChris Lattner // Remove duplicate spaces in the input file if requested. 13495ea04c38SGuy Benyei // Remove DOS style line endings. 13501961f14cSDavid Blaikie std::unique_ptr<MemoryBuffer> F = 1351ce5dd1acSRafael Espindola CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace); 13522c3e5cdfSChris Lattner 1353ee3c74fbSChris Lattner // Check that we have all of the expected strings, in order, in the input 1354ee3c74fbSChris Lattner // file. 1355caa5fc0cSChris Lattner StringRef Buffer = F->getBuffer(); 1356ee3c74fbSChris Lattner 13571961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(F), SMLoc()); 13581961f14cSDavid Blaikie 13591961f14cSDavid Blaikie /// VariableTable - This holds all the current filecheck variables. 13601961f14cSDavid Blaikie StringMap<StringRef> VariableTable; 13611961f14cSDavid Blaikie 1362f8bd2e5bSStephen Lin bool hasError = false; 1363ee3c74fbSChris Lattner 1364f8bd2e5bSStephen Lin unsigned i = 0, j = 0, e = CheckStrings.size(); 1365ee3c74fbSChris Lattner 1366f8bd2e5bSStephen Lin while (true) { 1367f8bd2e5bSStephen Lin StringRef CheckRegion; 1368f8bd2e5bSStephen Lin if (j == e) { 1369f8bd2e5bSStephen Lin CheckRegion = Buffer; 1370f8bd2e5bSStephen Lin } else { 1371f8bd2e5bSStephen Lin const CheckString &CheckLabelStr = CheckStrings[j]; 137285913ccaSJames Y Knight if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { 1373f8bd2e5bSStephen Lin ++j; 1374f8bd2e5bSStephen Lin continue; 1375da108b4eSChris Lattner } 1376da108b4eSChris Lattner 1377f8bd2e5bSStephen Lin // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG 1378f8bd2e5bSStephen Lin size_t MatchLabelLen = 0; 1379e93a3a08SStephen Lin size_t MatchLabelPos = CheckLabelStr.Check(SM, Buffer, true, 1380f8bd2e5bSStephen Lin MatchLabelLen, VariableTable); 1381f8bd2e5bSStephen Lin if (MatchLabelPos == StringRef::npos) { 1382f8bd2e5bSStephen Lin hasError = true; 1383f8bd2e5bSStephen Lin break; 1384f8bd2e5bSStephen Lin } 1385f8bd2e5bSStephen Lin 1386f8bd2e5bSStephen Lin CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen); 1387f8bd2e5bSStephen Lin Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen); 1388f8bd2e5bSStephen Lin ++j; 1389f8bd2e5bSStephen Lin } 1390f8bd2e5bSStephen Lin 1391f8bd2e5bSStephen Lin for ( ; i != j; ++i) { 1392f8bd2e5bSStephen Lin const CheckString &CheckStr = CheckStrings[i]; 1393f8bd2e5bSStephen Lin 1394f8bd2e5bSStephen Lin // Check each string within the scanned region, including a second check 1395f8bd2e5bSStephen Lin // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) 1396f8bd2e5bSStephen Lin size_t MatchLen = 0; 1397e93a3a08SStephen Lin size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen, 1398f8bd2e5bSStephen Lin VariableTable); 1399f8bd2e5bSStephen Lin 1400f8bd2e5bSStephen Lin if (MatchPos == StringRef::npos) { 1401f8bd2e5bSStephen Lin hasError = true; 1402f8bd2e5bSStephen Lin i = j; 1403f8bd2e5bSStephen Lin break; 1404f8bd2e5bSStephen Lin } 1405f8bd2e5bSStephen Lin 1406f8bd2e5bSStephen Lin CheckRegion = CheckRegion.substr(MatchPos + MatchLen); 1407f8bd2e5bSStephen Lin } 1408f8bd2e5bSStephen Lin 1409f8bd2e5bSStephen Lin if (j == e) 1410f8bd2e5bSStephen Lin break; 1411f8bd2e5bSStephen Lin } 1412f8bd2e5bSStephen Lin 1413f8bd2e5bSStephen Lin return hasError ? 1 : 0; 1414ee3c74fbSChris Lattner } 1415