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 
65*85913ccaSJames Y Knight static cl::opt<bool> MatchFullLines(
66*85913ccaSJames Y Knight     "match-full-lines", cl::init(false),
67*85913ccaSJames Y Knight     cl::desc("Require all positive matches to cover an entire input line.\n"
68*85913ccaSJames Y Knight              "Allows leading and trailing whitespace if --strict-whitespace\n"
69*85913ccaSJames Y Knight              "is not also passed."));
70*85913ccaSJames 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.
8938820972SMatt Arsenault     CheckEOF
9038820972SMatt Arsenault   };
9138820972SMatt Arsenault }
92eba55822SJakob Stoklund Olesen 
9338820972SMatt Arsenault class Pattern {
9438820972SMatt Arsenault   SMLoc PatternLoc;
9591a1b2c9SMichael Liao 
9638820972SMatt Arsenault   Check::CheckType CheckTy;
9791a1b2c9SMichael Liao 
98b16ab0c4SChris Lattner   /// FixedStr - If non-empty, this pattern is a fixed string match with the
99b16ab0c4SChris Lattner   /// specified fixed string.
100221460e0SChris Lattner   StringRef FixedStr;
101b16ab0c4SChris Lattner 
102b16ab0c4SChris Lattner   /// RegEx - If non-empty, this is a regex pattern.
103b16ab0c4SChris Lattner   std::string RegExStr;
1048879e06dSChris Lattner 
10592987fb3SAlexander Kornienko   /// \brief Contains the number of line this pattern is in.
10692987fb3SAlexander Kornienko   unsigned LineNumber;
10792987fb3SAlexander Kornienko 
1088879e06dSChris Lattner   /// VariableUses - Entries in this vector map to uses of a variable in the
1098879e06dSChris Lattner   /// pattern, e.g. "foo[[bar]]baz".  In this case, the RegExStr will contain
1108879e06dSChris Lattner   /// "foobaz" and we'll get an entry in this vector that tells us to insert the
1118879e06dSChris Lattner   /// value of bar at offset 3.
1128879e06dSChris Lattner   std::vector<std::pair<StringRef, unsigned> > VariableUses;
1138879e06dSChris Lattner 
114e8b8f1bcSEli Bendersky   /// VariableDefs - Maps definitions of variables to their parenthesized
115e8b8f1bcSEli Bendersky   /// capture numbers.
116e8b8f1bcSEli Bendersky   /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 1.
117e8b8f1bcSEli Bendersky   std::map<StringRef, unsigned> VariableDefs;
1188879e06dSChris Lattner 
1193b40b445SChris Lattner public:
1203b40b445SChris Lattner 
12138820972SMatt Arsenault   Pattern(Check::CheckType Ty)
12238820972SMatt Arsenault     : CheckTy(Ty) { }
12374d50731SChris Lattner 
1240b707eb8SMichael Liao   /// getLoc - Return the location in source code.
1250b707eb8SMichael Liao   SMLoc getLoc() const { return PatternLoc; }
1260b707eb8SMichael Liao 
12713df4626SMatt Arsenault   /// ParsePattern - Parse the given string into the Pattern. Prefix provides
12813df4626SMatt Arsenault   /// which prefix is being matched, SM provides the SourceMgr used for error
12913df4626SMatt Arsenault   /// reports, and LineNumber is the line number in the input file from which
13013df4626SMatt Arsenault   /// the pattern string was read.  Returns true in case of an error, false
13113df4626SMatt Arsenault   /// otherwise.
13213df4626SMatt Arsenault   bool ParsePattern(StringRef PatternStr,
13313df4626SMatt Arsenault                     StringRef Prefix,
13413df4626SMatt Arsenault                     SourceMgr &SM,
13513df4626SMatt Arsenault                     unsigned LineNumber);
1363b40b445SChris Lattner 
1373b40b445SChris Lattner   /// Match - Match the pattern string against the input buffer Buffer.  This
1383b40b445SChris Lattner   /// returns the position that is matched or npos if there is no match.  If
1393b40b445SChris Lattner   /// there is a match, the size of the matched string is returned in MatchLen.
1408879e06dSChris Lattner   ///
1418879e06dSChris Lattner   /// The VariableTable StringMap provides the current values of filecheck
1428879e06dSChris Lattner   /// variables and is updated if this match defines new values.
1438879e06dSChris Lattner   size_t Match(StringRef Buffer, size_t &MatchLen,
1448879e06dSChris Lattner                StringMap<StringRef> &VariableTable) const;
145b16ab0c4SChris Lattner 
146e0ef65abSDaniel Dunbar   /// PrintFailureInfo - Print additional information about a failure to match
147e0ef65abSDaniel Dunbar   /// involving this pattern.
148e0ef65abSDaniel Dunbar   void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
149e0ef65abSDaniel Dunbar                         const StringMap<StringRef> &VariableTable) const;
150e0ef65abSDaniel Dunbar 
151f8bd2e5bSStephen Lin   bool hasVariable() const { return !(VariableUses.empty() &&
152f8bd2e5bSStephen Lin                                       VariableDefs.empty()); }
153f8bd2e5bSStephen Lin 
15438820972SMatt Arsenault   Check::CheckType getCheckTy() const { return CheckTy; }
15591a1b2c9SMichael Liao 
156b16ab0c4SChris Lattner private:
157e8b8f1bcSEli Bendersky   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
158e8b8f1bcSEli Bendersky   void AddBackrefToRegEx(unsigned BackrefNum);
159fd29d886SDaniel Dunbar 
160fd29d886SDaniel Dunbar   /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of
161fd29d886SDaniel Dunbar   /// matching this pattern at the start of \arg Buffer; a distance of zero
162fd29d886SDaniel Dunbar   /// should correspond to a perfect match.
163fd29d886SDaniel Dunbar   unsigned ComputeMatchDistance(StringRef Buffer,
164fd29d886SDaniel Dunbar                                const StringMap<StringRef> &VariableTable) const;
16592987fb3SAlexander Kornienko 
16692987fb3SAlexander Kornienko   /// \brief Evaluates expression and stores the result to \p Value.
16792987fb3SAlexander Kornienko   /// \return true on success. false when the expression has invalid syntax.
16892987fb3SAlexander Kornienko   bool EvaluateExpression(StringRef Expr, std::string &Value) const;
169061d2baaSEli Bendersky 
170061d2baaSEli Bendersky   /// \brief Finds the closing sequence of a regex variable usage or
171061d2baaSEli Bendersky   /// definition. Str has to point in the beginning of the definition
172061d2baaSEli Bendersky   /// (right after the opening sequence).
173061d2baaSEli Bendersky   /// \return offset of the closing sequence within Str, or npos if it was not
174061d2baaSEli Bendersky   /// found.
17581e5cd9eSAdrian Prantl   size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
1763b40b445SChris Lattner };
1773b40b445SChris Lattner 
1788879e06dSChris Lattner 
17913df4626SMatt Arsenault bool Pattern::ParsePattern(StringRef PatternStr,
18013df4626SMatt Arsenault                            StringRef Prefix,
18113df4626SMatt Arsenault                            SourceMgr &SM,
18292987fb3SAlexander Kornienko                            unsigned LineNumber) {
183*85913ccaSJames Y Knight   bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot;
184*85913ccaSJames Y Knight 
18592987fb3SAlexander Kornienko   this->LineNumber = LineNumber;
1860a4c44bdSChris Lattner   PatternLoc = SMLoc::getFromPointer(PatternStr.data());
1870a4c44bdSChris Lattner 
18874d50731SChris Lattner   // Ignore trailing whitespace.
18974d50731SChris Lattner   while (!PatternStr.empty() &&
19074d50731SChris Lattner          (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
19174d50731SChris Lattner     PatternStr = PatternStr.substr(0, PatternStr.size()-1);
19274d50731SChris Lattner 
19374d50731SChris Lattner   // Check that there is something on the line.
19474d50731SChris Lattner   if (PatternStr.empty()) {
19503b80a40SChris Lattner     SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
19603b80a40SChris Lattner                     "found empty check string with prefix '" +
19713df4626SMatt Arsenault                     Prefix + ":'");
19874d50731SChris Lattner     return true;
19974d50731SChris Lattner   }
20074d50731SChris Lattner 
201221460e0SChris Lattner   // Check to see if this is a fixed string, or if it has regex pieces.
202*85913ccaSJames Y Knight   if (!MatchFullLinesHere &&
203*85913ccaSJames Y Knight       (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
204*85913ccaSJames Y Knight                                  PatternStr.find("[[") == StringRef::npos))) {
205221460e0SChris Lattner     FixedStr = PatternStr;
206221460e0SChris Lattner     return false;
207221460e0SChris Lattner   }
208221460e0SChris Lattner 
209*85913ccaSJames Y Knight   if (MatchFullLinesHere) {
210*85913ccaSJames Y Knight     RegExStr += '^';
211*85913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
212*85913ccaSJames Y Knight       RegExStr += " *";
213*85913ccaSJames Y Knight   }
214*85913ccaSJames Y Knight 
2158879e06dSChris Lattner   // Paren value #0 is for the fully matched string.  Any new parenthesized
21653e0679dSChris Lattner   // values add from there.
2178879e06dSChris Lattner   unsigned CurParen = 1;
2188879e06dSChris Lattner 
219b16ab0c4SChris Lattner   // Otherwise, there is at least one regex piece.  Build up the regex pattern
220b16ab0c4SChris Lattner   // by escaping scary characters in fixed strings, building up one big regex.
221f08d2db9SChris Lattner   while (!PatternStr.empty()) {
2228879e06dSChris Lattner     // RegEx matches.
22353e0679dSChris Lattner     if (PatternStr.startswith("{{")) {
22443d50d4aSEli Bendersky       // This is the start of a regex match.  Scan for the }}.
225f08d2db9SChris Lattner       size_t End = PatternStr.find("}}");
226f08d2db9SChris Lattner       if (End == StringRef::npos) {
227f08d2db9SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
22803b80a40SChris Lattner                         SourceMgr::DK_Error,
22903b80a40SChris Lattner                         "found start of regex string with no end '}}'");
230f08d2db9SChris Lattner         return true;
231f08d2db9SChris Lattner       }
232f08d2db9SChris Lattner 
233e53c95f1SChris Lattner       // Enclose {{}} patterns in parens just like [[]] even though we're not
234e53c95f1SChris Lattner       // capturing the result for any purpose.  This is required in case the
235e53c95f1SChris Lattner       // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
236e53c95f1SChris Lattner       // want this to turn into: "abc(x|z)def" not "abcx|zdef".
237e53c95f1SChris Lattner       RegExStr += '(';
238e53c95f1SChris Lattner       ++CurParen;
239e53c95f1SChris Lattner 
2408879e06dSChris Lattner       if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
2418879e06dSChris Lattner         return true;
242e53c95f1SChris Lattner       RegExStr += ')';
24353e0679dSChris Lattner 
2448879e06dSChris Lattner       PatternStr = PatternStr.substr(End+2);
2458879e06dSChris Lattner       continue;
2468879e06dSChris Lattner     }
2478879e06dSChris Lattner 
2488879e06dSChris Lattner     // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
2498879e06dSChris Lattner     // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
2508879e06dSChris Lattner     // second form is [[foo]] which is a reference to foo.  The variable name
25157cb733bSDaniel Dunbar     // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
2528879e06dSChris Lattner     // it.  This is to catch some common errors.
25353e0679dSChris Lattner     if (PatternStr.startswith("[[")) {
254061d2baaSEli Bendersky       // Find the closing bracket pair ending the match.  End is going to be an
255061d2baaSEli Bendersky       // offset relative to the beginning of the match string.
25681e5cd9eSAdrian Prantl       size_t End = FindRegexVarEnd(PatternStr.substr(2), SM);
257061d2baaSEli Bendersky 
2588879e06dSChris Lattner       if (End == StringRef::npos) {
2598879e06dSChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
26003b80a40SChris Lattner                         SourceMgr::DK_Error,
26103b80a40SChris Lattner                         "invalid named regex reference, no ]] found");
262f08d2db9SChris Lattner         return true;
263f08d2db9SChris Lattner       }
264f08d2db9SChris Lattner 
265061d2baaSEli Bendersky       StringRef MatchStr = PatternStr.substr(2, End);
266061d2baaSEli Bendersky       PatternStr = PatternStr.substr(End+4);
2678879e06dSChris Lattner 
2688879e06dSChris Lattner       // Get the regex name (e.g. "foo").
2698879e06dSChris Lattner       size_t NameEnd = MatchStr.find(':');
2708879e06dSChris Lattner       StringRef Name = MatchStr.substr(0, NameEnd);
2718879e06dSChris Lattner 
2728879e06dSChris Lattner       if (Name.empty()) {
27303b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
27403b80a40SChris Lattner                         "invalid name in named regex: empty name");
2758879e06dSChris Lattner         return true;
2768879e06dSChris Lattner       }
2778879e06dSChris Lattner 
27892987fb3SAlexander Kornienko       // Verify that the name/expression is well formed. FileCheck currently
27992987fb3SAlexander Kornienko       // supports @LINE, @LINE+number, @LINE-number expressions. The check here
28092987fb3SAlexander Kornienko       // is relaxed, more strict check is performed in \c EvaluateExpression.
28192987fb3SAlexander Kornienko       bool IsExpression = false;
28292987fb3SAlexander Kornienko       for (unsigned i = 0, e = Name.size(); i != e; ++i) {
28392987fb3SAlexander Kornienko         if (i == 0 && Name[i] == '@') {
28492987fb3SAlexander Kornienko           if (NameEnd != StringRef::npos) {
28592987fb3SAlexander Kornienko             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
28692987fb3SAlexander Kornienko                             SourceMgr::DK_Error,
28792987fb3SAlexander Kornienko                             "invalid name in named regex definition");
28892987fb3SAlexander Kornienko             return true;
28992987fb3SAlexander Kornienko           }
29092987fb3SAlexander Kornienko           IsExpression = true;
29192987fb3SAlexander Kornienko           continue;
29292987fb3SAlexander Kornienko         }
29392987fb3SAlexander Kornienko         if (Name[i] != '_' && !isalnum(Name[i]) &&
29492987fb3SAlexander Kornienko             (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
2958879e06dSChris Lattner           SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
29603b80a40SChris Lattner                           SourceMgr::DK_Error, "invalid name in named regex");
2978879e06dSChris Lattner           return true;
2988879e06dSChris Lattner         }
29992987fb3SAlexander Kornienko       }
3008879e06dSChris Lattner 
3018879e06dSChris Lattner       // Name can't start with a digit.
30283c74e9fSGuy Benyei       if (isdigit(static_cast<unsigned char>(Name[0]))) {
30303b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
30403b80a40SChris Lattner                         "invalid name in named regex");
3058879e06dSChris Lattner         return true;
3068879e06dSChris Lattner       }
3078879e06dSChris Lattner 
3088879e06dSChris Lattner       // Handle [[foo]].
3098879e06dSChris Lattner       if (NameEnd == StringRef::npos) {
310e8b8f1bcSEli Bendersky         // Handle variables that were defined earlier on the same line by
311e8b8f1bcSEli Bendersky         // emitting a backreference.
312e8b8f1bcSEli Bendersky         if (VariableDefs.find(Name) != VariableDefs.end()) {
313e8b8f1bcSEli Bendersky           unsigned VarParenNum = VariableDefs[Name];
314e8b8f1bcSEli Bendersky           if (VarParenNum < 1 || VarParenNum > 9) {
315e8b8f1bcSEli Bendersky             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
316e8b8f1bcSEli Bendersky                             SourceMgr::DK_Error,
317e8b8f1bcSEli Bendersky                             "Can't back-reference more than 9 variables");
318e8b8f1bcSEli Bendersky             return true;
319e8b8f1bcSEli Bendersky           }
320e8b8f1bcSEli Bendersky           AddBackrefToRegEx(VarParenNum);
321e8b8f1bcSEli Bendersky         } else {
3228879e06dSChris Lattner           VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
323e8b8f1bcSEli Bendersky         }
3248879e06dSChris Lattner         continue;
3258879e06dSChris Lattner       }
3268879e06dSChris Lattner 
3278879e06dSChris Lattner       // Handle [[foo:.*]].
328e8b8f1bcSEli Bendersky       VariableDefs[Name] = CurParen;
3298879e06dSChris Lattner       RegExStr += '(';
3308879e06dSChris Lattner       ++CurParen;
3318879e06dSChris Lattner 
3328879e06dSChris Lattner       if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
3338879e06dSChris Lattner         return true;
3348879e06dSChris Lattner 
3358879e06dSChris Lattner       RegExStr += ')';
3368879e06dSChris Lattner     }
3378879e06dSChris Lattner 
3388879e06dSChris Lattner     // Handle fixed string matches.
3398879e06dSChris Lattner     // Find the end, which is the start of the next regex.
3408879e06dSChris Lattner     size_t FixedMatchEnd = PatternStr.find("{{");
3418879e06dSChris Lattner     FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
3426f4f77b7SHans Wennborg     RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
3438879e06dSChris Lattner     PatternStr = PatternStr.substr(FixedMatchEnd);
344f08d2db9SChris Lattner   }
345f08d2db9SChris Lattner 
346*85913ccaSJames Y Knight   if (MatchFullLinesHere) {
347*85913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
348*85913ccaSJames Y Knight       RegExStr += " *";
349*85913ccaSJames Y Knight     RegExStr += '$';
350*85913ccaSJames Y Knight   }
351*85913ccaSJames Y Knight 
35274d50731SChris Lattner   return false;
35374d50731SChris Lattner }
35474d50731SChris Lattner 
355e8b8f1bcSEli Bendersky bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen,
3568879e06dSChris Lattner                               SourceMgr &SM) {
357e8b8f1bcSEli Bendersky   Regex R(RS);
3588879e06dSChris Lattner   std::string Error;
3598879e06dSChris Lattner   if (!R.isValid(Error)) {
360e8b8f1bcSEli Bendersky     SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
36103b80a40SChris Lattner                     "invalid regex: " + Error);
3628879e06dSChris Lattner     return true;
3638879e06dSChris Lattner   }
3648879e06dSChris Lattner 
365e8b8f1bcSEli Bendersky   RegExStr += RS.str();
3668879e06dSChris Lattner   CurParen += R.getNumMatches();
3678879e06dSChris Lattner   return false;
3688879e06dSChris Lattner }
369b16ab0c4SChris Lattner 
370e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
371e8b8f1bcSEli Bendersky   assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
372e8b8f1bcSEli Bendersky   std::string Backref = std::string("\\") +
373e8b8f1bcSEli Bendersky                         std::string(1, '0' + BackrefNum);
374e8b8f1bcSEli Bendersky   RegExStr += Backref;
375e8b8f1bcSEli Bendersky }
376e8b8f1bcSEli Bendersky 
37792987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
37892987fb3SAlexander Kornienko   // The only supported expression is @LINE([\+-]\d+)?
37992987fb3SAlexander Kornienko   if (!Expr.startswith("@LINE"))
38092987fb3SAlexander Kornienko     return false;
38192987fb3SAlexander Kornienko   Expr = Expr.substr(StringRef("@LINE").size());
38292987fb3SAlexander Kornienko   int Offset = 0;
38392987fb3SAlexander Kornienko   if (!Expr.empty()) {
38492987fb3SAlexander Kornienko     if (Expr[0] == '+')
38592987fb3SAlexander Kornienko       Expr = Expr.substr(1);
38692987fb3SAlexander Kornienko     else if (Expr[0] != '-')
38792987fb3SAlexander Kornienko       return false;
38892987fb3SAlexander Kornienko     if (Expr.getAsInteger(10, Offset))
38992987fb3SAlexander Kornienko       return false;
39092987fb3SAlexander Kornienko   }
39192987fb3SAlexander Kornienko   Value = llvm::itostr(LineNumber + Offset);
39292987fb3SAlexander Kornienko   return true;
39392987fb3SAlexander Kornienko }
39492987fb3SAlexander Kornienko 
395f08d2db9SChris Lattner /// Match - Match the pattern string against the input buffer Buffer.  This
396f08d2db9SChris Lattner /// returns the position that is matched or npos if there is no match.  If
397f08d2db9SChris Lattner /// there is a match, the size of the matched string is returned in MatchLen.
3988879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
3998879e06dSChris Lattner                       StringMap<StringRef> &VariableTable) const {
400eba55822SJakob Stoklund Olesen   // If this is the EOF pattern, match it immediately.
40138820972SMatt Arsenault   if (CheckTy == Check::CheckEOF) {
402eba55822SJakob Stoklund Olesen     MatchLen = 0;
403eba55822SJakob Stoklund Olesen     return Buffer.size();
404eba55822SJakob Stoklund Olesen   }
405eba55822SJakob Stoklund Olesen 
406221460e0SChris Lattner   // If this is a fixed string pattern, just match it now.
407221460e0SChris Lattner   if (!FixedStr.empty()) {
408221460e0SChris Lattner     MatchLen = FixedStr.size();
409221460e0SChris Lattner     return Buffer.find(FixedStr);
410221460e0SChris Lattner   }
411221460e0SChris Lattner 
412b16ab0c4SChris Lattner   // Regex match.
4138879e06dSChris Lattner 
4148879e06dSChris Lattner   // If there are variable uses, we need to create a temporary string with the
4158879e06dSChris Lattner   // actual value.
4168879e06dSChris Lattner   StringRef RegExToMatch = RegExStr;
4178879e06dSChris Lattner   std::string TmpStr;
4188879e06dSChris Lattner   if (!VariableUses.empty()) {
4198879e06dSChris Lattner     TmpStr = RegExStr;
4208879e06dSChris Lattner 
4218879e06dSChris Lattner     unsigned InsertOffset = 0;
4228f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
42392987fb3SAlexander Kornienko       std::string Value;
42492987fb3SAlexander Kornienko 
4258f870499SBenjamin Kramer       if (VariableUse.first[0] == '@') {
4268f870499SBenjamin Kramer         if (!EvaluateExpression(VariableUse.first, Value))
42792987fb3SAlexander Kornienko           return StringRef::npos;
42892987fb3SAlexander Kornienko       } else {
429e0ef65abSDaniel Dunbar         StringMap<StringRef>::iterator it =
4308f870499SBenjamin Kramer             VariableTable.find(VariableUse.first);
431e0ef65abSDaniel Dunbar         // If the variable is undefined, return an error.
432e0ef65abSDaniel Dunbar         if (it == VariableTable.end())
433e0ef65abSDaniel Dunbar           return StringRef::npos;
434e0ef65abSDaniel Dunbar 
4356f4f77b7SHans Wennborg         // Look up the value and escape it so that we can put it into the regex.
4366f4f77b7SHans Wennborg         Value += Regex::escape(it->second);
43792987fb3SAlexander Kornienko       }
4388879e06dSChris Lattner 
4398879e06dSChris Lattner       // Plop it into the regex at the adjusted offset.
4408f870499SBenjamin Kramer       TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset,
4418879e06dSChris Lattner                     Value.begin(), Value.end());
4428879e06dSChris Lattner       InsertOffset += Value.size();
4438879e06dSChris Lattner     }
4448879e06dSChris Lattner 
4458879e06dSChris Lattner     // Match the newly constructed regex.
4468879e06dSChris Lattner     RegExToMatch = TmpStr;
4478879e06dSChris Lattner   }
4488879e06dSChris Lattner 
4498879e06dSChris Lattner 
450b16ab0c4SChris Lattner   SmallVector<StringRef, 4> MatchInfo;
4518879e06dSChris Lattner   if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
452f08d2db9SChris Lattner     return StringRef::npos;
453b16ab0c4SChris Lattner 
454b16ab0c4SChris Lattner   // Successful regex match.
455b16ab0c4SChris Lattner   assert(!MatchInfo.empty() && "Didn't get any match");
456b16ab0c4SChris Lattner   StringRef FullMatch = MatchInfo[0];
457b16ab0c4SChris Lattner 
4588879e06dSChris Lattner   // If this defines any variables, remember their values.
4598f870499SBenjamin Kramer   for (const auto &VariableDef : VariableDefs) {
4608f870499SBenjamin Kramer     assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
4618f870499SBenjamin Kramer     VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
4620a4c44bdSChris Lattner   }
4630a4c44bdSChris Lattner 
464b16ab0c4SChris Lattner   MatchLen = FullMatch.size();
465b16ab0c4SChris Lattner   return FullMatch.data()-Buffer.data();
466f08d2db9SChris Lattner }
467f08d2db9SChris Lattner 
468fd29d886SDaniel Dunbar unsigned Pattern::ComputeMatchDistance(StringRef Buffer,
469fd29d886SDaniel Dunbar                               const StringMap<StringRef> &VariableTable) const {
470fd29d886SDaniel Dunbar   // Just compute the number of matching characters. For regular expressions, we
471fd29d886SDaniel Dunbar   // just compare against the regex itself and hope for the best.
472fd29d886SDaniel Dunbar   //
473fd29d886SDaniel Dunbar   // FIXME: One easy improvement here is have the regex lib generate a single
474fd29d886SDaniel Dunbar   // example regular expression which matches, and use that as the example
475fd29d886SDaniel Dunbar   // string.
476fd29d886SDaniel Dunbar   StringRef ExampleString(FixedStr);
477fd29d886SDaniel Dunbar   if (ExampleString.empty())
478fd29d886SDaniel Dunbar     ExampleString = RegExStr;
479fd29d886SDaniel Dunbar 
480e9aa36c8SDaniel Dunbar   // Only compare up to the first line in the buffer, or the string size.
481e9aa36c8SDaniel Dunbar   StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
482e9aa36c8SDaniel Dunbar   BufferPrefix = BufferPrefix.split('\n').first;
483e9aa36c8SDaniel Dunbar   return BufferPrefix.edit_distance(ExampleString);
484fd29d886SDaniel Dunbar }
485fd29d886SDaniel Dunbar 
486e0ef65abSDaniel Dunbar void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
487e0ef65abSDaniel Dunbar                                const StringMap<StringRef> &VariableTable) const{
488e0ef65abSDaniel Dunbar   // If this was a regular expression using variables, print the current
489e0ef65abSDaniel Dunbar   // variable values.
490e0ef65abSDaniel Dunbar   if (!VariableUses.empty()) {
4918f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
492e69170a1SAlp Toker       SmallString<256> Msg;
493e69170a1SAlp Toker       raw_svector_ostream OS(Msg);
4948f870499SBenjamin Kramer       StringRef Var = VariableUse.first;
49592987fb3SAlexander Kornienko       if (Var[0] == '@') {
49692987fb3SAlexander Kornienko         std::string Value;
49792987fb3SAlexander Kornienko         if (EvaluateExpression(Var, Value)) {
49892987fb3SAlexander Kornienko           OS << "with expression \"";
49992987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\" equal to \"";
50092987fb3SAlexander Kornienko           OS.write_escaped(Value) << "\"";
50192987fb3SAlexander Kornienko         } else {
50292987fb3SAlexander Kornienko           OS << "uses incorrect expression \"";
50392987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
50492987fb3SAlexander Kornienko         }
50592987fb3SAlexander Kornienko       } else {
50692987fb3SAlexander Kornienko         StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
507e0ef65abSDaniel Dunbar 
508e0ef65abSDaniel Dunbar         // Check for undefined variable references.
509e0ef65abSDaniel Dunbar         if (it == VariableTable.end()) {
510e0ef65abSDaniel Dunbar           OS << "uses undefined variable \"";
51192987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
512e0ef65abSDaniel Dunbar         } else {
513e0ef65abSDaniel Dunbar           OS << "with variable \"";
514e0ef65abSDaniel Dunbar           OS.write_escaped(Var) << "\" equal to \"";
515e0ef65abSDaniel Dunbar           OS.write_escaped(it->second) << "\"";
516e0ef65abSDaniel Dunbar         }
51792987fb3SAlexander Kornienko       }
518e0ef65abSDaniel Dunbar 
51903b80a40SChris Lattner       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
52003b80a40SChris Lattner                       OS.str());
521e0ef65abSDaniel Dunbar     }
522e0ef65abSDaniel Dunbar   }
523fd29d886SDaniel Dunbar 
524fd29d886SDaniel Dunbar   // Attempt to find the closest/best fuzzy match.  Usually an error happens
525fd29d886SDaniel Dunbar   // because some string in the output didn't exactly match. In these cases, we
526fd29d886SDaniel Dunbar   // would like to show the user a best guess at what "should have" matched, to
527fd29d886SDaniel Dunbar   // save them having to actually check the input manually.
528fd29d886SDaniel Dunbar   size_t NumLinesForward = 0;
529fd29d886SDaniel Dunbar   size_t Best = StringRef::npos;
530fd29d886SDaniel Dunbar   double BestQuality = 0;
531fd29d886SDaniel Dunbar 
532fd29d886SDaniel Dunbar   // Use an arbitrary 4k limit on how far we will search.
5332bf486ebSDan Gohman   for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
534fd29d886SDaniel Dunbar     if (Buffer[i] == '\n')
535fd29d886SDaniel Dunbar       ++NumLinesForward;
536fd29d886SDaniel Dunbar 
537df22bbf7SDan Gohman     // Patterns have leading whitespace stripped, so skip whitespace when
538df22bbf7SDan Gohman     // looking for something which looks like a pattern.
539df22bbf7SDan Gohman     if (Buffer[i] == ' ' || Buffer[i] == '\t')
540df22bbf7SDan Gohman       continue;
541df22bbf7SDan Gohman 
542fd29d886SDaniel Dunbar     // Compute the "quality" of this match as an arbitrary combination of the
543fd29d886SDaniel Dunbar     // match distance and the number of lines skipped to get to this match.
544fd29d886SDaniel Dunbar     unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
545fd29d886SDaniel Dunbar     double Quality = Distance + (NumLinesForward / 100.);
546fd29d886SDaniel Dunbar 
547fd29d886SDaniel Dunbar     if (Quality < BestQuality || Best == StringRef::npos) {
548fd29d886SDaniel Dunbar       Best = i;
549fd29d886SDaniel Dunbar       BestQuality = Quality;
550fd29d886SDaniel Dunbar     }
551fd29d886SDaniel Dunbar   }
552fd29d886SDaniel Dunbar 
553fd29d886SDaniel Dunbar   // Print the "possible intended match here" line if we found something
554c069cc8eSDaniel Dunbar   // reasonable and not equal to what we showed in the "scanning from here"
555c069cc8eSDaniel Dunbar   // line.
556c069cc8eSDaniel Dunbar   if (Best && Best != StringRef::npos && BestQuality < 50) {
557fd29d886SDaniel Dunbar       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
55803b80a40SChris Lattner                       SourceMgr::DK_Note, "possible intended match here");
559fd29d886SDaniel Dunbar 
560fd29d886SDaniel Dunbar     // FIXME: If we wanted to be really friendly we would show why the match
561fd29d886SDaniel Dunbar     // failed, as it can be hard to spot simple one character differences.
562fd29d886SDaniel Dunbar   }
563e0ef65abSDaniel Dunbar }
56474d50731SChris Lattner 
56581e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
566061d2baaSEli Bendersky   // Offset keeps track of the current offset within the input Str
567061d2baaSEli Bendersky   size_t Offset = 0;
568061d2baaSEli Bendersky   // [...] Nesting depth
569061d2baaSEli Bendersky   size_t BracketDepth = 0;
570061d2baaSEli Bendersky 
571061d2baaSEli Bendersky   while (!Str.empty()) {
572061d2baaSEli Bendersky     if (Str.startswith("]]") && BracketDepth == 0)
573061d2baaSEli Bendersky       return Offset;
574061d2baaSEli Bendersky     if (Str[0] == '\\') {
575061d2baaSEli Bendersky       // Backslash escapes the next char within regexes, so skip them both.
576061d2baaSEli Bendersky       Str = Str.substr(2);
577061d2baaSEli Bendersky       Offset += 2;
578061d2baaSEli Bendersky     } else {
579061d2baaSEli Bendersky       switch (Str[0]) {
580061d2baaSEli Bendersky         default:
581061d2baaSEli Bendersky           break;
582061d2baaSEli Bendersky         case '[':
583061d2baaSEli Bendersky           BracketDepth++;
584061d2baaSEli Bendersky           break;
585061d2baaSEli Bendersky         case ']':
58681e5cd9eSAdrian Prantl           if (BracketDepth == 0) {
58781e5cd9eSAdrian Prantl             SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
58881e5cd9eSAdrian Prantl                             SourceMgr::DK_Error,
58981e5cd9eSAdrian Prantl                             "missing closing \"]\" for regex variable");
59081e5cd9eSAdrian Prantl             exit(1);
59181e5cd9eSAdrian Prantl           }
592061d2baaSEli Bendersky           BracketDepth--;
593061d2baaSEli Bendersky           break;
594061d2baaSEli Bendersky       }
595061d2baaSEli Bendersky       Str = Str.substr(1);
596061d2baaSEli Bendersky       Offset++;
597061d2baaSEli Bendersky     }
598061d2baaSEli Bendersky   }
599061d2baaSEli Bendersky 
600061d2baaSEli Bendersky   return StringRef::npos;
601061d2baaSEli Bendersky }
602061d2baaSEli Bendersky 
603061d2baaSEli Bendersky 
60474d50731SChris Lattner //===----------------------------------------------------------------------===//
60574d50731SChris Lattner // Check Strings.
60674d50731SChris Lattner //===----------------------------------------------------------------------===//
6073b40b445SChris Lattner 
6083b40b445SChris Lattner /// CheckString - This is a check that we found in the input file.
6093b40b445SChris Lattner struct CheckString {
6103b40b445SChris Lattner   /// Pat - The pattern to match.
6113b40b445SChris Lattner   Pattern Pat;
61226cccfe1SChris Lattner 
61313df4626SMatt Arsenault   /// Prefix - Which prefix name this check matched.
61413df4626SMatt Arsenault   StringRef Prefix;
61513df4626SMatt Arsenault 
61626cccfe1SChris Lattner   /// Loc - The location in the match file that the check string was specified.
61726cccfe1SChris Lattner   SMLoc Loc;
61826cccfe1SChris Lattner 
61938820972SMatt Arsenault   /// CheckTy - Specify what kind of check this is. e.g. CHECK-NEXT: directive,
62038820972SMatt Arsenault   /// as opposed to a CHECK: directive.
621*85913ccaSJames Y Knight   //  Check::CheckType CheckTy;
622f8bd2e5bSStephen Lin 
62391a1b2c9SMichael Liao   /// DagNotStrings - These are all of the strings that are disallowed from
624236d2d5eSChris Lattner   /// occurring between this match string and the previous one (or start of
625236d2d5eSChris Lattner   /// file).
62691a1b2c9SMichael Liao   std::vector<Pattern> DagNotStrings;
627236d2d5eSChris Lattner 
628*85913ccaSJames Y Knight   CheckString(const Pattern &P, StringRef S, SMLoc L)
629*85913ccaSJames Y Knight       : Pat(P), Prefix(S), Loc(L) {}
630dcc7d48dSMichael Liao 
63191a1b2c9SMichael Liao   /// Check - Match check string and its "not strings" and/or "dag strings".
632e93a3a08SStephen Lin   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
633f8bd2e5bSStephen Lin                size_t &MatchLen, StringMap<StringRef> &VariableTable) const;
634dcc7d48dSMichael Liao 
635dcc7d48dSMichael Liao   /// CheckNext - Verify there is a single line in the given buffer.
636dcc7d48dSMichael Liao   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
637dcc7d48dSMichael Liao 
63801ac1707SDuncan P. N. Exon Smith   /// CheckSame - Verify there is no newline in the given buffer.
63901ac1707SDuncan P. N. Exon Smith   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
64001ac1707SDuncan P. N. Exon Smith 
641dcc7d48dSMichael Liao   /// CheckNot - Verify there's no "not strings" in the given buffer.
642dcc7d48dSMichael Liao   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
64391a1b2c9SMichael Liao                 const std::vector<const Pattern *> &NotStrings,
64491a1b2c9SMichael Liao                 StringMap<StringRef> &VariableTable) const;
64591a1b2c9SMichael Liao 
64691a1b2c9SMichael Liao   /// CheckDag - Match "dag strings" and their mixed "not strings".
64791a1b2c9SMichael Liao   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
64891a1b2c9SMichael Liao                   std::vector<const Pattern *> &NotStrings,
649dcc7d48dSMichael Liao                   StringMap<StringRef> &VariableTable) const;
65026cccfe1SChris Lattner };
65126cccfe1SChris Lattner 
6525ea04c38SGuy Benyei /// Canonicalize whitespaces in the input file. Line endings are replaced
6535ea04c38SGuy Benyei /// with UNIX-style '\n'.
6545ea04c38SGuy Benyei ///
6555ea04c38SGuy Benyei /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace
6565ea04c38SGuy Benyei /// characters to a single space.
6571961f14cSDavid Blaikie static std::unique_ptr<MemoryBuffer>
6581961f14cSDavid Blaikie CanonicalizeInputFile(std::unique_ptr<MemoryBuffer> MB,
6595ea04c38SGuy Benyei                       bool PreserveHorizontal) {
6600e45d24aSChris Lattner   SmallString<128> NewFile;
661a2f8fc5aSChris Lattner   NewFile.reserve(MB->getBufferSize());
662a2f8fc5aSChris Lattner 
663a2f8fc5aSChris Lattner   for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
664a2f8fc5aSChris Lattner        Ptr != End; ++Ptr) {
665fd781bf0SNAKAMURA Takumi     // Eliminate trailing dosish \r.
666fd781bf0SNAKAMURA Takumi     if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
667fd781bf0SNAKAMURA Takumi       continue;
668fd781bf0SNAKAMURA Takumi     }
669fd781bf0SNAKAMURA Takumi 
6705ea04c38SGuy Benyei     // If current char is not a horizontal whitespace or if horizontal
6715ea04c38SGuy Benyei     // whitespace canonicalization is disabled, dump it to output as is.
6725ea04c38SGuy Benyei     if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) {
673a2f8fc5aSChris Lattner       NewFile.push_back(*Ptr);
674a2f8fc5aSChris Lattner       continue;
675a2f8fc5aSChris Lattner     }
676a2f8fc5aSChris Lattner 
677a2f8fc5aSChris Lattner     // Otherwise, add one space and advance over neighboring space.
678a2f8fc5aSChris Lattner     NewFile.push_back(' ');
679a2f8fc5aSChris Lattner     while (Ptr+1 != End &&
680a2f8fc5aSChris Lattner            (Ptr[1] == ' ' || Ptr[1] == '\t'))
681a2f8fc5aSChris Lattner       ++Ptr;
682a2f8fc5aSChris Lattner   }
683a2f8fc5aSChris Lattner 
6841961f14cSDavid Blaikie   return std::unique_ptr<MemoryBuffer>(
6851961f14cSDavid Blaikie       MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()));
686a2f8fc5aSChris Lattner }
687a2f8fc5aSChris Lattner 
68838820972SMatt Arsenault static bool IsPartOfWord(char c) {
68938820972SMatt Arsenault   return (isalnum(c) || c == '-' || c == '_');
69038820972SMatt Arsenault }
69138820972SMatt Arsenault 
69213df4626SMatt Arsenault // Get the size of the prefix extension.
69313df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) {
69413df4626SMatt Arsenault   switch (Ty) {
69513df4626SMatt Arsenault   case Check::CheckNone:
69613df4626SMatt Arsenault     return 0;
69713df4626SMatt Arsenault 
69813df4626SMatt Arsenault   case Check::CheckPlain:
69913df4626SMatt Arsenault     return sizeof(":") - 1;
70013df4626SMatt Arsenault 
70113df4626SMatt Arsenault   case Check::CheckNext:
70213df4626SMatt Arsenault     return sizeof("-NEXT:") - 1;
70313df4626SMatt Arsenault 
70401ac1707SDuncan P. N. Exon Smith   case Check::CheckSame:
70501ac1707SDuncan P. N. Exon Smith     return sizeof("-SAME:") - 1;
70601ac1707SDuncan P. N. Exon Smith 
70713df4626SMatt Arsenault   case Check::CheckNot:
70813df4626SMatt Arsenault     return sizeof("-NOT:") - 1;
70913df4626SMatt Arsenault 
71013df4626SMatt Arsenault   case Check::CheckDAG:
71113df4626SMatt Arsenault     return sizeof("-DAG:") - 1;
71213df4626SMatt Arsenault 
71313df4626SMatt Arsenault   case Check::CheckLabel:
71413df4626SMatt Arsenault     return sizeof("-LABEL:") - 1;
71513df4626SMatt Arsenault 
71613df4626SMatt Arsenault   case Check::CheckEOF:
71713df4626SMatt Arsenault     llvm_unreachable("Should not be using EOF size");
71813df4626SMatt Arsenault   }
71913df4626SMatt Arsenault 
72013df4626SMatt Arsenault   llvm_unreachable("Bad check type");
72113df4626SMatt Arsenault }
72213df4626SMatt Arsenault 
72313df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
724c4d2d471SMatt Arsenault   char NextChar = Buffer[Prefix.size()];
72538820972SMatt Arsenault 
72638820972SMatt Arsenault   // Verify that the : is present after the prefix.
72713df4626SMatt Arsenault   if (NextChar == ':')
72838820972SMatt Arsenault     return Check::CheckPlain;
72938820972SMatt Arsenault 
73013df4626SMatt Arsenault   if (NextChar != '-')
73138820972SMatt Arsenault     return Check::CheckNone;
73238820972SMatt Arsenault 
733c4d2d471SMatt Arsenault   StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
73413df4626SMatt Arsenault   if (Rest.startswith("NEXT:"))
73538820972SMatt Arsenault     return Check::CheckNext;
73638820972SMatt Arsenault 
73701ac1707SDuncan P. N. Exon Smith   if (Rest.startswith("SAME:"))
73801ac1707SDuncan P. N. Exon Smith     return Check::CheckSame;
73901ac1707SDuncan P. N. Exon Smith 
74013df4626SMatt Arsenault   if (Rest.startswith("NOT:"))
74138820972SMatt Arsenault     return Check::CheckNot;
74238820972SMatt Arsenault 
74313df4626SMatt Arsenault   if (Rest.startswith("DAG:"))
74438820972SMatt Arsenault     return Check::CheckDAG;
74538820972SMatt Arsenault 
74613df4626SMatt Arsenault   if (Rest.startswith("LABEL:"))
74738820972SMatt Arsenault     return Check::CheckLabel;
74813df4626SMatt Arsenault 
74913df4626SMatt Arsenault   return Check::CheckNone;
75038820972SMatt Arsenault }
75138820972SMatt Arsenault 
75213df4626SMatt Arsenault // From the given position, find the next character after the word.
75313df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) {
75413df4626SMatt Arsenault   while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
75513df4626SMatt Arsenault     ++Loc;
75613df4626SMatt Arsenault   return Loc;
75713df4626SMatt Arsenault }
75813df4626SMatt Arsenault 
75913df4626SMatt Arsenault // Try to find the first match in buffer for any prefix. If a valid match is
76013df4626SMatt Arsenault // found, return that prefix and set its type and location.  If there are almost
76113df4626SMatt Arsenault // matches (e.g. the actual prefix string is found, but is not an actual check
76213df4626SMatt Arsenault // string), but no valid match, return an empty string and set the position to
76313df4626SMatt Arsenault // resume searching from. If no partial matches are found, return an empty
76413df4626SMatt Arsenault // string and the location will be StringRef::npos. If one prefix is a substring
76513df4626SMatt Arsenault // of another, the maximal match should be found. e.g. if "A" and "AA" are
76613df4626SMatt Arsenault // prefixes then AA-CHECK: should match the second one.
76713df4626SMatt Arsenault static StringRef FindFirstCandidateMatch(StringRef &Buffer,
76813df4626SMatt Arsenault                                          Check::CheckType &CheckTy,
76913df4626SMatt Arsenault                                          size_t &CheckLoc) {
77013df4626SMatt Arsenault   StringRef FirstPrefix;
77113df4626SMatt Arsenault   size_t FirstLoc = StringRef::npos;
77213df4626SMatt Arsenault   size_t SearchLoc = StringRef::npos;
77313df4626SMatt Arsenault   Check::CheckType FirstTy = Check::CheckNone;
77413df4626SMatt Arsenault 
77513df4626SMatt Arsenault   CheckTy = Check::CheckNone;
77613df4626SMatt Arsenault   CheckLoc = StringRef::npos;
77713df4626SMatt Arsenault 
7788f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
77913df4626SMatt Arsenault     size_t PrefixLoc = Buffer.find(Prefix);
78013df4626SMatt Arsenault 
78113df4626SMatt Arsenault     if (PrefixLoc == StringRef::npos)
78213df4626SMatt Arsenault       continue;
78313df4626SMatt Arsenault 
78413df4626SMatt Arsenault     // Track where we are searching for invalid prefixes that look almost right.
78513df4626SMatt Arsenault     // We need to only advance to the first partial match on the next attempt
78613df4626SMatt Arsenault     // since a partial match could be a substring of a later, valid prefix.
78713df4626SMatt Arsenault     // Need to skip to the end of the word, otherwise we could end up
78813df4626SMatt Arsenault     // matching a prefix in a substring later.
78913df4626SMatt Arsenault     if (PrefixLoc < SearchLoc)
79013df4626SMatt Arsenault       SearchLoc = SkipWord(Buffer, PrefixLoc);
79113df4626SMatt Arsenault 
79213df4626SMatt Arsenault     // We only want to find the first match to avoid skipping some.
79313df4626SMatt Arsenault     if (PrefixLoc > FirstLoc)
79413df4626SMatt Arsenault       continue;
795a7181a1bSAlexey Samsonov     // If one matching check-prefix is a prefix of another, choose the
796a7181a1bSAlexey Samsonov     // longer one.
797a7181a1bSAlexey Samsonov     if (PrefixLoc == FirstLoc && Prefix.size() < FirstPrefix.size())
798a7181a1bSAlexey Samsonov       continue;
79913df4626SMatt Arsenault 
80013df4626SMatt Arsenault     StringRef Rest = Buffer.drop_front(PrefixLoc);
80113df4626SMatt Arsenault     // Make sure we have actually found the prefix, and not a word containing
80213df4626SMatt Arsenault     // it. This should also prevent matching the wrong prefix when one is a
80313df4626SMatt Arsenault     // substring of another.
80413df4626SMatt Arsenault     if (PrefixLoc != 0 && IsPartOfWord(Buffer[PrefixLoc - 1]))
80543b5f572SDaniel Sanders       FirstTy = Check::CheckNone;
80643b5f572SDaniel Sanders     else
80743b5f572SDaniel Sanders       FirstTy = FindCheckType(Rest, Prefix);
80813df4626SMatt Arsenault 
80913df4626SMatt Arsenault     FirstLoc = PrefixLoc;
810a7181a1bSAlexey Samsonov     FirstPrefix = Prefix;
81113df4626SMatt Arsenault   }
81213df4626SMatt Arsenault 
813a7181a1bSAlexey Samsonov   // If the first prefix is invalid, we should continue the search after it.
814a7181a1bSAlexey Samsonov   if (FirstTy == Check::CheckNone) {
81513df4626SMatt Arsenault     CheckLoc = SearchLoc;
816a7181a1bSAlexey Samsonov     return "";
817a7181a1bSAlexey Samsonov   }
818a7181a1bSAlexey Samsonov 
81913df4626SMatt Arsenault   CheckTy = FirstTy;
82013df4626SMatt Arsenault   CheckLoc = FirstLoc;
82113df4626SMatt Arsenault   return FirstPrefix;
82213df4626SMatt Arsenault }
82313df4626SMatt Arsenault 
82413df4626SMatt Arsenault static StringRef FindFirstMatchingPrefix(StringRef &Buffer,
82513df4626SMatt Arsenault                                          unsigned &LineNumber,
82613df4626SMatt Arsenault                                          Check::CheckType &CheckTy,
82713df4626SMatt Arsenault                                          size_t &CheckLoc) {
82813df4626SMatt Arsenault   while (!Buffer.empty()) {
82913df4626SMatt Arsenault     StringRef Prefix = FindFirstCandidateMatch(Buffer, CheckTy, CheckLoc);
83013df4626SMatt Arsenault     // If we found a real match, we are done.
83113df4626SMatt Arsenault     if (!Prefix.empty()) {
83213df4626SMatt Arsenault       LineNumber += Buffer.substr(0, CheckLoc).count('\n');
83313df4626SMatt Arsenault       return Prefix;
83413df4626SMatt Arsenault     }
83513df4626SMatt Arsenault 
83613df4626SMatt Arsenault     // We didn't find any almost matches either, we are also done.
83713df4626SMatt Arsenault     if (CheckLoc == StringRef::npos)
83813df4626SMatt Arsenault       return StringRef();
83913df4626SMatt Arsenault 
84013df4626SMatt Arsenault     LineNumber += Buffer.substr(0, CheckLoc + 1).count('\n');
84113df4626SMatt Arsenault 
84213df4626SMatt Arsenault     // Advance to the last possible match we found and try again.
84313df4626SMatt Arsenault     Buffer = Buffer.drop_front(CheckLoc + 1);
84413df4626SMatt Arsenault   }
84513df4626SMatt Arsenault 
84613df4626SMatt Arsenault   return StringRef();
84738820972SMatt Arsenault }
848ee3c74fbSChris Lattner 
849ee3c74fbSChris Lattner /// ReadCheckFile - Read the check file, which specifies the sequence of
850ee3c74fbSChris Lattner /// expected strings.  The strings are added to the CheckStrings vector.
85143d50d4aSEli Bendersky /// Returns true in case of an error, false otherwise.
852ee3c74fbSChris Lattner static bool ReadCheckFile(SourceMgr &SM,
85326cccfe1SChris Lattner                           std::vector<CheckString> &CheckStrings) {
854adf21f2aSRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
855adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(CheckFilename);
856adf21f2aSRafael Espindola   if (std::error_code EC = FileOrErr.getError()) {
857adf21f2aSRafael Espindola     errs() << "Could not open check file '" << CheckFilename
858adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
859ee3c74fbSChris Lattner     return true;
860ee3c74fbSChris Lattner   }
861a2f8fc5aSChris Lattner 
862a2f8fc5aSChris Lattner   // If we want to canonicalize whitespace, strip excess whitespace from the
8635ea04c38SGuy Benyei   // buffer containing the CHECK lines. Remove DOS style line endings.
8643560ff2cSRafael Espindola   std::unique_ptr<MemoryBuffer> F = CanonicalizeInputFile(
8653560ff2cSRafael Espindola       std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace);
866ee3c74fbSChris Lattner 
86710f10cedSChris Lattner   // Find all instances of CheckPrefix followed by : in the file.
868caa5fc0cSChris Lattner   StringRef Buffer = F->getBuffer();
86956ccdbbdSAlexander Kornienko 
8701961f14cSDavid Blaikie   SM.AddNewSourceBuffer(std::move(F), SMLoc());
8711961f14cSDavid Blaikie 
87256ccdbbdSAlexander Kornienko   std::vector<Pattern> ImplicitNegativeChecks;
87356ccdbbdSAlexander Kornienko   for (const auto &PatternString : ImplicitCheckNot) {
87456ccdbbdSAlexander Kornienko     // Create a buffer with fake command line content in order to display the
87556ccdbbdSAlexander Kornienko     // command line option responsible for the specific implicit CHECK-NOT.
876ff43d69dSDavid Blaikie     std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str();
87756ccdbbdSAlexander Kornienko     std::string Suffix = "'";
8783560ff2cSRafael Espindola     std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
8793560ff2cSRafael Espindola         Prefix + PatternString + Suffix, "command line");
8803560ff2cSRafael Espindola 
88156ccdbbdSAlexander Kornienko     StringRef PatternInBuffer =
88256ccdbbdSAlexander Kornienko         CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
8831961f14cSDavid Blaikie     SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
88456ccdbbdSAlexander Kornienko 
88556ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot));
88656ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
88756ccdbbdSAlexander Kornienko                                                "IMPLICIT-CHECK", SM, 0);
88856ccdbbdSAlexander Kornienko   }
88956ccdbbdSAlexander Kornienko 
89056ccdbbdSAlexander Kornienko 
89156ccdbbdSAlexander Kornienko   std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
892236d2d5eSChris Lattner 
89343d50d4aSEli Bendersky   // LineNumber keeps track of the line on which CheckPrefix instances are
89443d50d4aSEli Bendersky   // found.
89592987fb3SAlexander Kornienko   unsigned LineNumber = 1;
89692987fb3SAlexander Kornienko 
897ee3c74fbSChris Lattner   while (1) {
89813df4626SMatt Arsenault     Check::CheckType CheckTy;
89913df4626SMatt Arsenault     size_t PrefixLoc;
90013df4626SMatt Arsenault 
90113df4626SMatt Arsenault     // See if a prefix occurs in the memory buffer.
90213df4626SMatt Arsenault     StringRef UsedPrefix = FindFirstMatchingPrefix(Buffer,
90313df4626SMatt Arsenault                                                    LineNumber,
90413df4626SMatt Arsenault                                                    CheckTy,
90513df4626SMatt Arsenault                                                    PrefixLoc);
90613df4626SMatt Arsenault     if (UsedPrefix.empty())
907ee3c74fbSChris Lattner       break;
908ee3c74fbSChris Lattner 
90913df4626SMatt Arsenault     Buffer = Buffer.drop_front(PrefixLoc);
91092987fb3SAlexander Kornienko 
91113df4626SMatt Arsenault     // Location to use for error messages.
91213df4626SMatt Arsenault     const char *UsedPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1);
91392987fb3SAlexander Kornienko 
91413df4626SMatt Arsenault     // PrefixLoc is to the start of the prefix. Skip to the end.
91513df4626SMatt Arsenault     Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
91610f10cedSChris Lattner 
91738820972SMatt Arsenault     // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
91838820972SMatt Arsenault     // leading and trailing whitespace.
919236d2d5eSChris Lattner     Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
920ee3c74fbSChris Lattner 
921ee3c74fbSChris Lattner     // Scan ahead to the end of line.
922caa5fc0cSChris Lattner     size_t EOL = Buffer.find_first_of("\n\r");
923ee3c74fbSChris Lattner 
924838fb09aSDan Gohman     // Remember the location of the start of the pattern, for diagnostics.
925838fb09aSDan Gohman     SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
926838fb09aSDan Gohman 
92774d50731SChris Lattner     // Parse the pattern.
92838820972SMatt Arsenault     Pattern P(CheckTy);
92913df4626SMatt Arsenault     if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber))
930ee3c74fbSChris Lattner       return true;
931ee3c74fbSChris Lattner 
932f8bd2e5bSStephen Lin     // Verify that CHECK-LABEL lines do not define or use variables
93338820972SMatt Arsenault     if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
93413df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
935f8bd2e5bSStephen Lin                       SourceMgr::DK_Error,
93613df4626SMatt Arsenault                       "found '" + UsedPrefix + "-LABEL:'"
93713df4626SMatt Arsenault                       " with variable definition or use");
938f8bd2e5bSStephen Lin       return true;
939f8bd2e5bSStephen Lin     }
940f8bd2e5bSStephen Lin 
941236d2d5eSChris Lattner     Buffer = Buffer.substr(EOL);
94274d50731SChris Lattner 
943da108b4eSChris Lattner     // Verify that CHECK-NEXT lines have at least one CHECK line before them.
94401ac1707SDuncan P. N. Exon Smith     if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
94501ac1707SDuncan P. N. Exon Smith         CheckStrings.empty()) {
94601ac1707SDuncan P. N. Exon Smith       StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
94713df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
94803b80a40SChris Lattner                       SourceMgr::DK_Error,
94901ac1707SDuncan P. N. Exon Smith                       "found '" + UsedPrefix + "-" + Type + "' without previous '"
95013df4626SMatt Arsenault                       + UsedPrefix + ": line");
951da108b4eSChris Lattner       return true;
952da108b4eSChris Lattner     }
953da108b4eSChris Lattner 
95491a1b2c9SMichael Liao     // Handle CHECK-DAG/-NOT.
95538820972SMatt Arsenault     if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
95691a1b2c9SMichael Liao       DagNotMatches.push_back(P);
95774d50731SChris Lattner       continue;
95874d50731SChris Lattner     }
95974d50731SChris Lattner 
960ee3c74fbSChris Lattner     // Okay, add the string we captured to the output vector and move on.
961*85913ccaSJames Y Knight     CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
96291a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
96356ccdbbdSAlexander Kornienko     DagNotMatches = ImplicitNegativeChecks;
964ee3c74fbSChris Lattner   }
965ee3c74fbSChris Lattner 
96613df4626SMatt Arsenault   // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
96713df4626SMatt Arsenault   // prefix as a filler for the error message.
96891a1b2c9SMichael Liao   if (!DagNotMatches.empty()) {
969f5e2fc47SBenjamin Kramer     CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(),
970*85913ccaSJames Y Knight                               SMLoc::getFromPointer(Buffer.data()));
97191a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
972eba55822SJakob Stoklund Olesen   }
973eba55822SJakob Stoklund Olesen 
974ee3c74fbSChris Lattner   if (CheckStrings.empty()) {
97513df4626SMatt Arsenault     errs() << "error: no check strings found with prefix"
97613df4626SMatt Arsenault            << (CheckPrefixes.size() > 1 ? "es " : " ");
9773e3ef2f2SChris Bieneman     prefix_iterator I = CheckPrefixes.begin();
9783e3ef2f2SChris Bieneman     prefix_iterator E = CheckPrefixes.end();
9793e3ef2f2SChris Bieneman     if (I != E) {
9803e3ef2f2SChris Bieneman       errs() << "\'" << *I << ":'";
9813e3ef2f2SChris Bieneman       ++I;
98213df4626SMatt Arsenault     }
9833e3ef2f2SChris Bieneman     for (; I != E; ++I)
9843e3ef2f2SChris Bieneman       errs() << ", \'" << *I << ":'";
98513df4626SMatt Arsenault 
98613df4626SMatt Arsenault     errs() << '\n';
987ee3c74fbSChris Lattner     return true;
988ee3c74fbSChris Lattner   }
989ee3c74fbSChris Lattner 
990ee3c74fbSChris Lattner   return false;
991ee3c74fbSChris Lattner }
992ee3c74fbSChris Lattner 
9933c76c523SCraig Topper static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc,
99491a1b2c9SMichael Liao                              const Pattern &Pat, StringRef Buffer,
995e0ef65abSDaniel Dunbar                              StringMap<StringRef> &VariableTable) {
996da108b4eSChris Lattner   // Otherwise, we have an error, emit an error message.
99791a1b2c9SMichael Liao   SM.PrintMessage(Loc, SourceMgr::DK_Error,
99803b80a40SChris Lattner                   "expected string not found in input");
999da108b4eSChris Lattner 
1000da108b4eSChris Lattner   // Print the "scanning from here" line.  If the current position is at the
1001da108b4eSChris Lattner   // end of a line, advance to the start of the next line.
1002caa5fc0cSChris Lattner   Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
1003da108b4eSChris Lattner 
100403b80a40SChris Lattner   SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
100503b80a40SChris Lattner                   "scanning from here");
1006e0ef65abSDaniel Dunbar 
1007e0ef65abSDaniel Dunbar   // Allow the pattern to print additional information if desired.
100891a1b2c9SMichael Liao   Pat.PrintFailureInfo(SM, Buffer, VariableTable);
100991a1b2c9SMichael Liao }
101091a1b2c9SMichael Liao 
101191a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
101291a1b2c9SMichael Liao                              StringRef Buffer,
101391a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) {
101491a1b2c9SMichael Liao   PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
1015da108b4eSChris Lattner }
1016da108b4eSChris Lattner 
101737183584SChris Lattner /// CountNumNewlinesBetween - Count the number of newlines in the specified
101837183584SChris Lattner /// range.
1019592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range,
1020592fe880SRichard Smith                                         const char *&FirstNewLine) {
1021da108b4eSChris Lattner   unsigned NumNewLines = 0;
102237183584SChris Lattner   while (1) {
1023da108b4eSChris Lattner     // Scan for newline.
102437183584SChris Lattner     Range = Range.substr(Range.find_first_of("\n\r"));
102537183584SChris Lattner     if (Range.empty()) return NumNewLines;
1026da108b4eSChris Lattner 
1027da108b4eSChris Lattner     ++NumNewLines;
1028da108b4eSChris Lattner 
1029da108b4eSChris Lattner     // Handle \n\r and \r\n as a single newline.
103037183584SChris Lattner     if (Range.size() > 1 &&
103137183584SChris Lattner         (Range[1] == '\n' || Range[1] == '\r') &&
103237183584SChris Lattner         (Range[0] != Range[1]))
103337183584SChris Lattner       Range = Range.substr(1);
103437183584SChris Lattner     Range = Range.substr(1);
1035592fe880SRichard Smith 
1036592fe880SRichard Smith     if (NumNewLines == 1)
1037592fe880SRichard Smith       FirstNewLine = Range.begin();
1038da108b4eSChris Lattner   }
1039da108b4eSChris Lattner }
1040da108b4eSChris Lattner 
1041dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
1042e93a3a08SStephen Lin                           bool IsLabelScanMode, size_t &MatchLen,
1043dcc7d48dSMichael Liao                           StringMap<StringRef> &VariableTable) const {
104491a1b2c9SMichael Liao   size_t LastPos = 0;
104591a1b2c9SMichael Liao   std::vector<const Pattern *> NotStrings;
104691a1b2c9SMichael Liao 
1047e93a3a08SStephen Lin   // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1048e93a3a08SStephen Lin   // bounds; we have not processed variable definitions within the bounded block
1049e93a3a08SStephen Lin   // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1050e93a3a08SStephen Lin   // over the block again (including the last CHECK-LABEL) in normal mode.
1051e93a3a08SStephen Lin   if (!IsLabelScanMode) {
105291a1b2c9SMichael Liao     // Match "dag strings" (with mixed "not strings" if any).
105391a1b2c9SMichael Liao     LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable);
105491a1b2c9SMichael Liao     if (LastPos == StringRef::npos)
105591a1b2c9SMichael Liao       return StringRef::npos;
1056e93a3a08SStephen Lin   }
105791a1b2c9SMichael Liao 
105891a1b2c9SMichael Liao   // Match itself from the last position after matching CHECK-DAG.
105991a1b2c9SMichael Liao   StringRef MatchBuffer = Buffer.substr(LastPos);
106091a1b2c9SMichael Liao   size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
1061dcc7d48dSMichael Liao   if (MatchPos == StringRef::npos) {
106291a1b2c9SMichael Liao     PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
1063dcc7d48dSMichael Liao     return StringRef::npos;
1064dcc7d48dSMichael Liao   }
1065dcc7d48dSMichael Liao 
1066e93a3a08SStephen Lin   // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1067e93a3a08SStephen Lin   // or CHECK-NOT
1068e93a3a08SStephen Lin   if (!IsLabelScanMode) {
106991a1b2c9SMichael Liao     StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1070dcc7d48dSMichael Liao 
1071dcc7d48dSMichael Liao     // If this check is a "CHECK-NEXT", verify that the previous match was on
1072dcc7d48dSMichael Liao     // the previous line (i.e. that there is one newline between them).
1073dcc7d48dSMichael Liao     if (CheckNext(SM, SkippedRegion))
1074dcc7d48dSMichael Liao       return StringRef::npos;
1075dcc7d48dSMichael Liao 
107601ac1707SDuncan P. N. Exon Smith     // If this check is a "CHECK-SAME", verify that the previous match was on
107701ac1707SDuncan P. N. Exon Smith     // the same line (i.e. that there is no newline between them).
107801ac1707SDuncan P. N. Exon Smith     if (CheckSame(SM, SkippedRegion))
107901ac1707SDuncan P. N. Exon Smith       return StringRef::npos;
108001ac1707SDuncan P. N. Exon Smith 
1081dcc7d48dSMichael Liao     // If this match had "not strings", verify that they don't exist in the
1082dcc7d48dSMichael Liao     // skipped region.
108391a1b2c9SMichael Liao     if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
1084dcc7d48dSMichael Liao       return StringRef::npos;
1085f8bd2e5bSStephen Lin   }
1086dcc7d48dSMichael Liao 
10877dfb92b9SMehdi Amini   return LastPos + MatchPos;
1088dcc7d48dSMichael Liao }
1089dcc7d48dSMichael Liao 
1090dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
1091*85913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckNext)
1092dcc7d48dSMichael Liao     return false;
1093dcc7d48dSMichael Liao 
1094dcc7d48dSMichael Liao   // Count the number of newlines between the previous match and this one.
1095dcc7d48dSMichael Liao   assert(Buffer.data() !=
1096dcc7d48dSMichael Liao          SM.getMemoryBuffer(
1097dcc7d48dSMichael Liao            SM.FindBufferContainingLoc(
1098dcc7d48dSMichael Liao              SMLoc::getFromPointer(Buffer.data())))->getBufferStart() &&
1099dcc7d48dSMichael Liao          "CHECK-NEXT can't be the first check in a file");
1100dcc7d48dSMichael Liao 
110166f09ad0SCraig Topper   const char *FirstNewLine = nullptr;
1102592fe880SRichard Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1103dcc7d48dSMichael Liao 
1104dcc7d48dSMichael Liao   if (NumNewLines == 0) {
110513df4626SMatt Arsenault     SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix +
1106dcc7d48dSMichael Liao                     "-NEXT: is on the same line as previous match");
1107dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
1108dcc7d48dSMichael Liao                     SourceMgr::DK_Note, "'next' match was here");
1109dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1110dcc7d48dSMichael Liao                     "previous match ended here");
1111dcc7d48dSMichael Liao     return true;
1112dcc7d48dSMichael Liao   }
1113dcc7d48dSMichael Liao 
1114dcc7d48dSMichael Liao   if (NumNewLines != 1) {
111513df4626SMatt Arsenault     SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix +
1116dcc7d48dSMichael Liao                     "-NEXT: is not on the line after the previous match");
1117dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
1118dcc7d48dSMichael Liao                     SourceMgr::DK_Note, "'next' match was here");
1119dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1120dcc7d48dSMichael Liao                     "previous match ended here");
1121592fe880SRichard Smith     SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
1122592fe880SRichard Smith                     "non-matching line after previous match is here");
1123dcc7d48dSMichael Liao     return true;
1124dcc7d48dSMichael Liao   }
1125dcc7d48dSMichael Liao 
1126dcc7d48dSMichael Liao   return false;
1127dcc7d48dSMichael Liao }
1128dcc7d48dSMichael Liao 
112901ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
1130*85913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckSame)
113101ac1707SDuncan P. N. Exon Smith     return false;
113201ac1707SDuncan P. N. Exon Smith 
113301ac1707SDuncan P. N. Exon Smith   // Count the number of newlines between the previous match and this one.
113401ac1707SDuncan P. N. Exon Smith   assert(Buffer.data() !=
113501ac1707SDuncan P. N. Exon Smith              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
113601ac1707SDuncan P. N. Exon Smith                                     SMLoc::getFromPointer(Buffer.data())))
113701ac1707SDuncan P. N. Exon Smith                  ->getBufferStart() &&
113801ac1707SDuncan P. N. Exon Smith          "CHECK-SAME can't be the first check in a file");
113901ac1707SDuncan P. N. Exon Smith 
114001ac1707SDuncan P. N. Exon Smith   const char *FirstNewLine = nullptr;
114101ac1707SDuncan P. N. Exon Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
114201ac1707SDuncan P. N. Exon Smith 
114301ac1707SDuncan P. N. Exon Smith   if (NumNewLines != 0) {
114401ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(Loc, SourceMgr::DK_Error,
114501ac1707SDuncan P. N. Exon Smith                     Prefix +
114601ac1707SDuncan P. N. Exon Smith                         "-SAME: is not on the same line as the previous match");
114701ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
114801ac1707SDuncan P. N. Exon Smith                     "'next' match was here");
114901ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
115001ac1707SDuncan P. N. Exon Smith                     "previous match ended here");
115101ac1707SDuncan P. N. Exon Smith     return true;
115201ac1707SDuncan P. N. Exon Smith   }
115301ac1707SDuncan P. N. Exon Smith 
115401ac1707SDuncan P. N. Exon Smith   return false;
115501ac1707SDuncan P. N. Exon Smith }
115601ac1707SDuncan P. N. Exon Smith 
1157dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
115891a1b2c9SMichael Liao                            const std::vector<const Pattern *> &NotStrings,
1159dcc7d48dSMichael Liao                            StringMap<StringRef> &VariableTable) const {
11608f870499SBenjamin Kramer   for (const Pattern *Pat : NotStrings) {
116138820972SMatt Arsenault     assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
116291a1b2c9SMichael Liao 
1163dcc7d48dSMichael Liao     size_t MatchLen = 0;
116491a1b2c9SMichael Liao     size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
1165dcc7d48dSMichael Liao 
1166dcc7d48dSMichael Liao     if (Pos == StringRef::npos) continue;
1167dcc7d48dSMichael Liao 
1168dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos),
1169dcc7d48dSMichael Liao                     SourceMgr::DK_Error,
117013df4626SMatt Arsenault                     Prefix + "-NOT: string occurred!");
117191a1b2c9SMichael Liao     SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
117213df4626SMatt Arsenault                     Prefix + "-NOT: pattern specified here");
1173dcc7d48dSMichael Liao     return true;
1174dcc7d48dSMichael Liao   }
1175dcc7d48dSMichael Liao 
1176dcc7d48dSMichael Liao   return false;
1177dcc7d48dSMichael Liao }
1178dcc7d48dSMichael Liao 
117991a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
118091a1b2c9SMichael Liao                              std::vector<const Pattern *> &NotStrings,
118191a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) const {
118291a1b2c9SMichael Liao   if (DagNotStrings.empty())
118391a1b2c9SMichael Liao     return 0;
118491a1b2c9SMichael Liao 
118591a1b2c9SMichael Liao   size_t LastPos = 0;
118691a1b2c9SMichael Liao   size_t StartPos = LastPos;
118791a1b2c9SMichael Liao 
11888f870499SBenjamin Kramer   for (const Pattern &Pat : DagNotStrings) {
118938820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG ||
119038820972SMatt Arsenault             Pat.getCheckTy() == Check::CheckNot) &&
119191a1b2c9SMichael Liao            "Invalid CHECK-DAG or CHECK-NOT!");
119291a1b2c9SMichael Liao 
119338820972SMatt Arsenault     if (Pat.getCheckTy() == Check::CheckNot) {
119491a1b2c9SMichael Liao       NotStrings.push_back(&Pat);
119591a1b2c9SMichael Liao       continue;
119691a1b2c9SMichael Liao     }
119791a1b2c9SMichael Liao 
119838820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
119991a1b2c9SMichael Liao 
120091a1b2c9SMichael Liao     size_t MatchLen = 0, MatchPos;
120191a1b2c9SMichael Liao 
120291a1b2c9SMichael Liao     // CHECK-DAG always matches from the start.
120391a1b2c9SMichael Liao     StringRef MatchBuffer = Buffer.substr(StartPos);
120491a1b2c9SMichael Liao     MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
120591a1b2c9SMichael Liao     // With a group of CHECK-DAGs, a single mismatching means the match on
120691a1b2c9SMichael Liao     // that group of CHECK-DAGs fails immediately.
120791a1b2c9SMichael Liao     if (MatchPos == StringRef::npos) {
120891a1b2c9SMichael Liao       PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
120991a1b2c9SMichael Liao       return StringRef::npos;
121091a1b2c9SMichael Liao     }
121191a1b2c9SMichael Liao     // Re-calc it as the offset relative to the start of the original string.
121291a1b2c9SMichael Liao     MatchPos += StartPos;
121391a1b2c9SMichael Liao 
121491a1b2c9SMichael Liao     if (!NotStrings.empty()) {
121591a1b2c9SMichael Liao       if (MatchPos < LastPos) {
121691a1b2c9SMichael Liao         // Reordered?
121791a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
121891a1b2c9SMichael Liao                         SourceMgr::DK_Error,
121913df4626SMatt Arsenault                         Prefix + "-DAG: found a match of CHECK-DAG"
122091a1b2c9SMichael Liao                         " reordering across a CHECK-NOT");
122191a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
122291a1b2c9SMichael Liao                         SourceMgr::DK_Note,
122313df4626SMatt Arsenault                         Prefix + "-DAG: the farthest match of CHECK-DAG"
122491a1b2c9SMichael Liao                         " is found here");
122591a1b2c9SMichael Liao         SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
122613df4626SMatt Arsenault                         Prefix + "-NOT: the crossed pattern specified"
122791a1b2c9SMichael Liao                         " here");
122891a1b2c9SMichael Liao         SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
122913df4626SMatt Arsenault                         Prefix + "-DAG: the reordered pattern specified"
123091a1b2c9SMichael Liao                         " here");
123191a1b2c9SMichael Liao         return StringRef::npos;
123291a1b2c9SMichael Liao       }
123391a1b2c9SMichael Liao       // All subsequent CHECK-DAGs should be matched from the farthest
123491a1b2c9SMichael Liao       // position of all precedent CHECK-DAGs (including this one.)
123591a1b2c9SMichael Liao       StartPos = LastPos;
123691a1b2c9SMichael Liao       // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
123791a1b2c9SMichael Liao       // CHECK-DAG, verify that there's no 'not' strings occurred in that
123891a1b2c9SMichael Liao       // region.
123991a1b2c9SMichael Liao       StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1240cf708c32STim Northover       if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
124191a1b2c9SMichael Liao         return StringRef::npos;
124291a1b2c9SMichael Liao       // Clear "not strings".
124391a1b2c9SMichael Liao       NotStrings.clear();
124491a1b2c9SMichael Liao     }
124591a1b2c9SMichael Liao 
124691a1b2c9SMichael Liao     // Update the last position with CHECK-DAG matches.
124791a1b2c9SMichael Liao     LastPos = std::max(MatchPos + MatchLen, LastPos);
124891a1b2c9SMichael Liao   }
124991a1b2c9SMichael Liao 
125091a1b2c9SMichael Liao   return LastPos;
125191a1b2c9SMichael Liao }
125291a1b2c9SMichael Liao 
125313df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores.
125413df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) {
125513df4626SMatt Arsenault   Regex Validator("^[a-zA-Z0-9_-]*$");
125613df4626SMatt Arsenault   return Validator.match(CheckPrefix);
125713df4626SMatt Arsenault }
125813df4626SMatt Arsenault 
125913df4626SMatt Arsenault static bool ValidateCheckPrefixes() {
126013df4626SMatt Arsenault   StringSet<> PrefixSet;
126113df4626SMatt Arsenault 
12628f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
126324412b14SEli Bendersky     // Reject empty prefixes.
126424412b14SEli Bendersky     if (Prefix == "")
126524412b14SEli Bendersky       return false;
126624412b14SEli Bendersky 
12670356975cSDavid Blaikie     if (!PrefixSet.insert(Prefix).second)
126813df4626SMatt Arsenault       return false;
126913df4626SMatt Arsenault 
127013df4626SMatt Arsenault     if (!ValidateCheckPrefix(Prefix))
127113df4626SMatt Arsenault       return false;
127213df4626SMatt Arsenault   }
127313df4626SMatt Arsenault 
127413df4626SMatt Arsenault   return true;
127513df4626SMatt Arsenault }
127613df4626SMatt Arsenault 
127713df4626SMatt Arsenault // I don't think there's a way to specify an initial value for cl::list,
127813df4626SMatt Arsenault // so if nothing was specified, add the default
127913df4626SMatt Arsenault static void AddCheckPrefixIfNeeded() {
128013df4626SMatt Arsenault   if (CheckPrefixes.empty())
128113df4626SMatt Arsenault     CheckPrefixes.push_back("CHECK");
1282c2735158SRui Ueyama }
1283c2735158SRui Ueyama 
1284ee3c74fbSChris Lattner int main(int argc, char **argv) {
1285ee3c74fbSChris Lattner   sys::PrintStackTraceOnErrorSignal();
1286ee3c74fbSChris Lattner   PrettyStackTraceProgram X(argc, argv);
1287ee3c74fbSChris Lattner   cl::ParseCommandLineOptions(argc, argv);
1288ee3c74fbSChris Lattner 
128913df4626SMatt Arsenault   if (!ValidateCheckPrefixes()) {
129013df4626SMatt Arsenault     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
129113df4626SMatt Arsenault               "start with a letter and contain only alphanumeric characters, "
129213df4626SMatt Arsenault               "hyphens and underscores\n";
1293c2735158SRui Ueyama     return 2;
1294c2735158SRui Ueyama   }
1295c2735158SRui Ueyama 
129613df4626SMatt Arsenault   AddCheckPrefixIfNeeded();
129713df4626SMatt Arsenault 
1298ee3c74fbSChris Lattner   SourceMgr SM;
1299ee3c74fbSChris Lattner 
1300ee3c74fbSChris Lattner   // Read the expected strings from the check file.
130126cccfe1SChris Lattner   std::vector<CheckString> CheckStrings;
1302ee3c74fbSChris Lattner   if (ReadCheckFile(SM, CheckStrings))
1303ee3c74fbSChris Lattner     return 2;
1304ee3c74fbSChris Lattner 
1305ee3c74fbSChris Lattner   // Open the file to check and add it to SourceMgr.
1306adf21f2aSRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
1307adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(InputFilename);
1308adf21f2aSRafael Espindola   if (std::error_code EC = FileOrErr.getError()) {
1309adf21f2aSRafael Espindola     errs() << "Could not open input file '" << InputFilename
1310adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
13118e1c6477SEli Bendersky     return 2;
1312ee3c74fbSChris Lattner   }
13133f6481d0SRafael Espindola   std::unique_ptr<MemoryBuffer> &File = FileOrErr.get();
13142c3e5cdfSChris Lattner 
13151b9f936fSJustin Bogner   if (File->getBufferSize() == 0 && !AllowEmptyInput) {
1316b692bed7SChris Lattner     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
13178e1c6477SEli Bendersky     return 2;
1318b692bed7SChris Lattner   }
1319b692bed7SChris Lattner 
13202c3e5cdfSChris Lattner   // Remove duplicate spaces in the input file if requested.
13215ea04c38SGuy Benyei   // Remove DOS style line endings.
13221961f14cSDavid Blaikie   std::unique_ptr<MemoryBuffer> F =
1323ce5dd1acSRafael Espindola       CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace);
13242c3e5cdfSChris Lattner 
1325ee3c74fbSChris Lattner   // Check that we have all of the expected strings, in order, in the input
1326ee3c74fbSChris Lattner   // file.
1327caa5fc0cSChris Lattner   StringRef Buffer = F->getBuffer();
1328ee3c74fbSChris Lattner 
13291961f14cSDavid Blaikie   SM.AddNewSourceBuffer(std::move(F), SMLoc());
13301961f14cSDavid Blaikie 
13311961f14cSDavid Blaikie   /// VariableTable - This holds all the current filecheck variables.
13321961f14cSDavid Blaikie   StringMap<StringRef> VariableTable;
13331961f14cSDavid Blaikie 
1334f8bd2e5bSStephen Lin   bool hasError = false;
1335ee3c74fbSChris Lattner 
1336f8bd2e5bSStephen Lin   unsigned i = 0, j = 0, e = CheckStrings.size();
1337ee3c74fbSChris Lattner 
1338f8bd2e5bSStephen Lin   while (true) {
1339f8bd2e5bSStephen Lin     StringRef CheckRegion;
1340f8bd2e5bSStephen Lin     if (j == e) {
1341f8bd2e5bSStephen Lin       CheckRegion = Buffer;
1342f8bd2e5bSStephen Lin     } else {
1343f8bd2e5bSStephen Lin       const CheckString &CheckLabelStr = CheckStrings[j];
1344*85913ccaSJames Y Knight       if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
1345f8bd2e5bSStephen Lin         ++j;
1346f8bd2e5bSStephen Lin         continue;
1347da108b4eSChris Lattner       }
1348da108b4eSChris Lattner 
1349f8bd2e5bSStephen Lin       // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1350f8bd2e5bSStephen Lin       size_t MatchLabelLen = 0;
1351e93a3a08SStephen Lin       size_t MatchLabelPos = CheckLabelStr.Check(SM, Buffer, true,
1352f8bd2e5bSStephen Lin                                                  MatchLabelLen, VariableTable);
1353f8bd2e5bSStephen Lin       if (MatchLabelPos == StringRef::npos) {
1354f8bd2e5bSStephen Lin         hasError = true;
1355f8bd2e5bSStephen Lin         break;
1356f8bd2e5bSStephen Lin       }
1357f8bd2e5bSStephen Lin 
1358f8bd2e5bSStephen Lin       CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
1359f8bd2e5bSStephen Lin       Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
1360f8bd2e5bSStephen Lin       ++j;
1361f8bd2e5bSStephen Lin     }
1362f8bd2e5bSStephen Lin 
1363f8bd2e5bSStephen Lin     for ( ; i != j; ++i) {
1364f8bd2e5bSStephen Lin       const CheckString &CheckStr = CheckStrings[i];
1365f8bd2e5bSStephen Lin 
1366f8bd2e5bSStephen Lin       // Check each string within the scanned region, including a second check
1367f8bd2e5bSStephen Lin       // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1368f8bd2e5bSStephen Lin       size_t MatchLen = 0;
1369e93a3a08SStephen Lin       size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen,
1370f8bd2e5bSStephen Lin                                        VariableTable);
1371f8bd2e5bSStephen Lin 
1372f8bd2e5bSStephen Lin       if (MatchPos == StringRef::npos) {
1373f8bd2e5bSStephen Lin         hasError = true;
1374f8bd2e5bSStephen Lin         i = j;
1375f8bd2e5bSStephen Lin         break;
1376f8bd2e5bSStephen Lin       }
1377f8bd2e5bSStephen Lin 
1378f8bd2e5bSStephen Lin       CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
1379f8bd2e5bSStephen Lin     }
1380f8bd2e5bSStephen Lin 
1381f8bd2e5bSStephen Lin     if (j == e)
1382f8bd2e5bSStephen Lin       break;
1383f8bd2e5bSStephen Lin   }
1384f8bd2e5bSStephen Lin 
1385f8bd2e5bSStephen Lin   return hasError ? 1 : 0;
1386ee3c74fbSChris Lattner }
1387