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')"));
48*fd557cb0SDaniel Sanders static cl::alias CheckPrefixesAlias(
49*fd557cb0SDaniel Sanders     "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
50*fd557cb0SDaniel Sanders     cl::NotHidden,
51*fd557cb0SDaniel Sanders     cl::desc(
52*fd557cb0SDaniel 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 
10338820972SMatt Arsenault   Check::CheckType CheckTy;
10491a1b2c9SMichael Liao 
105b16ab0c4SChris Lattner   /// FixedStr - If non-empty, this pattern is a fixed string match with the
106b16ab0c4SChris Lattner   /// specified fixed string.
107221460e0SChris Lattner   StringRef FixedStr;
108b16ab0c4SChris Lattner 
109b16ab0c4SChris Lattner   /// RegEx - If non-empty, this is a regex pattern.
110b16ab0c4SChris Lattner   std::string RegExStr;
1118879e06dSChris Lattner 
11292987fb3SAlexander Kornienko   /// \brief Contains the number of line this pattern is in.
11392987fb3SAlexander Kornienko   unsigned LineNumber;
11492987fb3SAlexander Kornienko 
1158879e06dSChris Lattner   /// VariableUses - Entries in this vector map to uses of a variable in the
1168879e06dSChris Lattner   /// pattern, e.g. "foo[[bar]]baz".  In this case, the RegExStr will contain
1178879e06dSChris Lattner   /// "foobaz" and we'll get an entry in this vector that tells us to insert the
1188879e06dSChris Lattner   /// value of bar at offset 3.
1198879e06dSChris Lattner   std::vector<std::pair<StringRef, unsigned> > VariableUses;
1208879e06dSChris Lattner 
121e8b8f1bcSEli Bendersky   /// VariableDefs - Maps definitions of variables to their parenthesized
122e8b8f1bcSEli Bendersky   /// capture numbers.
123e8b8f1bcSEli Bendersky   /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 1.
124e8b8f1bcSEli Bendersky   std::map<StringRef, unsigned> VariableDefs;
1258879e06dSChris Lattner 
1263b40b445SChris Lattner public:
1273b40b445SChris Lattner 
12838820972SMatt Arsenault   Pattern(Check::CheckType Ty)
12938820972SMatt Arsenault     : CheckTy(Ty) { }
13074d50731SChris Lattner 
1310b707eb8SMichael Liao   /// getLoc - Return the location in source code.
1320b707eb8SMichael Liao   SMLoc getLoc() const { return PatternLoc; }
1330b707eb8SMichael Liao 
13413df4626SMatt Arsenault   /// ParsePattern - Parse the given string into the Pattern. Prefix provides
13513df4626SMatt Arsenault   /// which prefix is being matched, SM provides the SourceMgr used for error
13613df4626SMatt Arsenault   /// reports, and LineNumber is the line number in the input file from which
13713df4626SMatt Arsenault   /// the pattern string was read.  Returns true in case of an error, false
13813df4626SMatt Arsenault   /// otherwise.
13913df4626SMatt Arsenault   bool ParsePattern(StringRef PatternStr,
14013df4626SMatt Arsenault                     StringRef Prefix,
14113df4626SMatt Arsenault                     SourceMgr &SM,
14213df4626SMatt Arsenault                     unsigned LineNumber);
1433b40b445SChris Lattner 
1443b40b445SChris Lattner   /// Match - Match the pattern string against the input buffer Buffer.  This
1453b40b445SChris Lattner   /// returns the position that is matched or npos if there is no match.  If
1463b40b445SChris Lattner   /// there is a match, the size of the matched string is returned in MatchLen.
1478879e06dSChris Lattner   ///
1488879e06dSChris Lattner   /// The VariableTable StringMap provides the current values of filecheck
1498879e06dSChris Lattner   /// variables and is updated if this match defines new values.
1508879e06dSChris Lattner   size_t Match(StringRef Buffer, size_t &MatchLen,
1518879e06dSChris Lattner                StringMap<StringRef> &VariableTable) const;
152b16ab0c4SChris Lattner 
153e0ef65abSDaniel Dunbar   /// PrintFailureInfo - Print additional information about a failure to match
154e0ef65abSDaniel Dunbar   /// involving this pattern.
155e0ef65abSDaniel Dunbar   void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
156e0ef65abSDaniel Dunbar                         const StringMap<StringRef> &VariableTable) const;
157e0ef65abSDaniel Dunbar 
158f8bd2e5bSStephen Lin   bool hasVariable() const { return !(VariableUses.empty() &&
159f8bd2e5bSStephen Lin                                       VariableDefs.empty()); }
160f8bd2e5bSStephen Lin 
16138820972SMatt Arsenault   Check::CheckType getCheckTy() const { return CheckTy; }
16291a1b2c9SMichael Liao 
163b16ab0c4SChris Lattner private:
164e8b8f1bcSEli Bendersky   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
165e8b8f1bcSEli Bendersky   void AddBackrefToRegEx(unsigned BackrefNum);
166fd29d886SDaniel Dunbar 
167fd29d886SDaniel Dunbar   /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of
168fd29d886SDaniel Dunbar   /// matching this pattern at the start of \arg Buffer; a distance of zero
169fd29d886SDaniel Dunbar   /// should correspond to a perfect match.
170fd29d886SDaniel Dunbar   unsigned ComputeMatchDistance(StringRef Buffer,
171fd29d886SDaniel Dunbar                                const StringMap<StringRef> &VariableTable) const;
17292987fb3SAlexander Kornienko 
17392987fb3SAlexander Kornienko   /// \brief Evaluates expression and stores the result to \p Value.
17492987fb3SAlexander Kornienko   /// \return true on success. false when the expression has invalid syntax.
17592987fb3SAlexander Kornienko   bool EvaluateExpression(StringRef Expr, std::string &Value) const;
176061d2baaSEli Bendersky 
177061d2baaSEli Bendersky   /// \brief Finds the closing sequence of a regex variable usage or
178061d2baaSEli Bendersky   /// definition. Str has to point in the beginning of the definition
179061d2baaSEli Bendersky   /// (right after the opening sequence).
180061d2baaSEli Bendersky   /// \return offset of the closing sequence within Str, or npos if it was not
181061d2baaSEli Bendersky   /// found.
18281e5cd9eSAdrian Prantl   size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
1833b40b445SChris Lattner };
1843b40b445SChris Lattner 
1858879e06dSChris Lattner 
18613df4626SMatt Arsenault bool Pattern::ParsePattern(StringRef PatternStr,
18713df4626SMatt Arsenault                            StringRef Prefix,
18813df4626SMatt Arsenault                            SourceMgr &SM,
18992987fb3SAlexander Kornienko                            unsigned LineNumber) {
19085913ccaSJames Y Knight   bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot;
19185913ccaSJames Y Knight 
19292987fb3SAlexander Kornienko   this->LineNumber = LineNumber;
1930a4c44bdSChris Lattner   PatternLoc = SMLoc::getFromPointer(PatternStr.data());
1940a4c44bdSChris Lattner 
19574d50731SChris Lattner   // Ignore trailing whitespace.
19674d50731SChris Lattner   while (!PatternStr.empty() &&
19774d50731SChris Lattner          (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
19874d50731SChris Lattner     PatternStr = PatternStr.substr(0, PatternStr.size()-1);
19974d50731SChris Lattner 
20074d50731SChris Lattner   // Check that there is something on the line.
20174d50731SChris Lattner   if (PatternStr.empty()) {
20203b80a40SChris Lattner     SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
20303b80a40SChris Lattner                     "found empty check string with prefix '" +
20413df4626SMatt Arsenault                     Prefix + ":'");
20574d50731SChris Lattner     return true;
20674d50731SChris Lattner   }
20774d50731SChris Lattner 
208221460e0SChris Lattner   // Check to see if this is a fixed string, or if it has regex pieces.
20985913ccaSJames Y Knight   if (!MatchFullLinesHere &&
21085913ccaSJames Y Knight       (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
21185913ccaSJames Y Knight                                  PatternStr.find("[[") == StringRef::npos))) {
212221460e0SChris Lattner     FixedStr = PatternStr;
213221460e0SChris Lattner     return false;
214221460e0SChris Lattner   }
215221460e0SChris Lattner 
21685913ccaSJames Y Knight   if (MatchFullLinesHere) {
21785913ccaSJames Y Knight     RegExStr += '^';
21885913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
21985913ccaSJames Y Knight       RegExStr += " *";
22085913ccaSJames Y Knight   }
22185913ccaSJames Y Knight 
2228879e06dSChris Lattner   // Paren value #0 is for the fully matched string.  Any new parenthesized
22353e0679dSChris Lattner   // values add from there.
2248879e06dSChris Lattner   unsigned CurParen = 1;
2258879e06dSChris Lattner 
226b16ab0c4SChris Lattner   // Otherwise, there is at least one regex piece.  Build up the regex pattern
227b16ab0c4SChris Lattner   // by escaping scary characters in fixed strings, building up one big regex.
228f08d2db9SChris Lattner   while (!PatternStr.empty()) {
2298879e06dSChris Lattner     // RegEx matches.
23053e0679dSChris Lattner     if (PatternStr.startswith("{{")) {
23143d50d4aSEli Bendersky       // This is the start of a regex match.  Scan for the }}.
232f08d2db9SChris Lattner       size_t End = PatternStr.find("}}");
233f08d2db9SChris Lattner       if (End == StringRef::npos) {
234f08d2db9SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
23503b80a40SChris Lattner                         SourceMgr::DK_Error,
23603b80a40SChris Lattner                         "found start of regex string with no end '}}'");
237f08d2db9SChris Lattner         return true;
238f08d2db9SChris Lattner       }
239f08d2db9SChris Lattner 
240e53c95f1SChris Lattner       // Enclose {{}} patterns in parens just like [[]] even though we're not
241e53c95f1SChris Lattner       // capturing the result for any purpose.  This is required in case the
242e53c95f1SChris Lattner       // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
243e53c95f1SChris Lattner       // want this to turn into: "abc(x|z)def" not "abcx|zdef".
244e53c95f1SChris Lattner       RegExStr += '(';
245e53c95f1SChris Lattner       ++CurParen;
246e53c95f1SChris Lattner 
2478879e06dSChris Lattner       if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
2488879e06dSChris Lattner         return true;
249e53c95f1SChris Lattner       RegExStr += ')';
25053e0679dSChris Lattner 
2518879e06dSChris Lattner       PatternStr = PatternStr.substr(End+2);
2528879e06dSChris Lattner       continue;
2538879e06dSChris Lattner     }
2548879e06dSChris Lattner 
2558879e06dSChris Lattner     // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
2568879e06dSChris Lattner     // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
2578879e06dSChris Lattner     // second form is [[foo]] which is a reference to foo.  The variable name
25857cb733bSDaniel Dunbar     // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
2598879e06dSChris Lattner     // it.  This is to catch some common errors.
26053e0679dSChris Lattner     if (PatternStr.startswith("[[")) {
261061d2baaSEli Bendersky       // Find the closing bracket pair ending the match.  End is going to be an
262061d2baaSEli Bendersky       // offset relative to the beginning of the match string.
26381e5cd9eSAdrian Prantl       size_t End = FindRegexVarEnd(PatternStr.substr(2), SM);
264061d2baaSEli Bendersky 
2658879e06dSChris Lattner       if (End == StringRef::npos) {
2668879e06dSChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
26703b80a40SChris Lattner                         SourceMgr::DK_Error,
26803b80a40SChris Lattner                         "invalid named regex reference, no ]] found");
269f08d2db9SChris Lattner         return true;
270f08d2db9SChris Lattner       }
271f08d2db9SChris Lattner 
272061d2baaSEli Bendersky       StringRef MatchStr = PatternStr.substr(2, End);
273061d2baaSEli Bendersky       PatternStr = PatternStr.substr(End+4);
2748879e06dSChris Lattner 
2758879e06dSChris Lattner       // Get the regex name (e.g. "foo").
2768879e06dSChris Lattner       size_t NameEnd = MatchStr.find(':');
2778879e06dSChris Lattner       StringRef Name = MatchStr.substr(0, NameEnd);
2788879e06dSChris Lattner 
2798879e06dSChris Lattner       if (Name.empty()) {
28003b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
28103b80a40SChris Lattner                         "invalid name in named regex: empty name");
2828879e06dSChris Lattner         return true;
2838879e06dSChris Lattner       }
2848879e06dSChris Lattner 
28592987fb3SAlexander Kornienko       // Verify that the name/expression is well formed. FileCheck currently
28692987fb3SAlexander Kornienko       // supports @LINE, @LINE+number, @LINE-number expressions. The check here
28792987fb3SAlexander Kornienko       // is relaxed, more strict check is performed in \c EvaluateExpression.
28892987fb3SAlexander Kornienko       bool IsExpression = false;
28992987fb3SAlexander Kornienko       for (unsigned i = 0, e = Name.size(); i != e; ++i) {
29092987fb3SAlexander Kornienko         if (i == 0 && Name[i] == '@') {
29192987fb3SAlexander Kornienko           if (NameEnd != StringRef::npos) {
29292987fb3SAlexander Kornienko             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
29392987fb3SAlexander Kornienko                             SourceMgr::DK_Error,
29492987fb3SAlexander Kornienko                             "invalid name in named regex definition");
29592987fb3SAlexander Kornienko             return true;
29692987fb3SAlexander Kornienko           }
29792987fb3SAlexander Kornienko           IsExpression = true;
29892987fb3SAlexander Kornienko           continue;
29992987fb3SAlexander Kornienko         }
30092987fb3SAlexander Kornienko         if (Name[i] != '_' && !isalnum(Name[i]) &&
30192987fb3SAlexander Kornienko             (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
3028879e06dSChris Lattner           SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
30303b80a40SChris Lattner                           SourceMgr::DK_Error, "invalid name in named regex");
3048879e06dSChris Lattner           return true;
3058879e06dSChris Lattner         }
30692987fb3SAlexander Kornienko       }
3078879e06dSChris Lattner 
3088879e06dSChris Lattner       // Name can't start with a digit.
30983c74e9fSGuy Benyei       if (isdigit(static_cast<unsigned char>(Name[0]))) {
31003b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
31103b80a40SChris Lattner                         "invalid name in named regex");
3128879e06dSChris Lattner         return true;
3138879e06dSChris Lattner       }
3148879e06dSChris Lattner 
3158879e06dSChris Lattner       // Handle [[foo]].
3168879e06dSChris Lattner       if (NameEnd == StringRef::npos) {
317e8b8f1bcSEli Bendersky         // Handle variables that were defined earlier on the same line by
318e8b8f1bcSEli Bendersky         // emitting a backreference.
319e8b8f1bcSEli Bendersky         if (VariableDefs.find(Name) != VariableDefs.end()) {
320e8b8f1bcSEli Bendersky           unsigned VarParenNum = VariableDefs[Name];
321e8b8f1bcSEli Bendersky           if (VarParenNum < 1 || VarParenNum > 9) {
322e8b8f1bcSEli Bendersky             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
323e8b8f1bcSEli Bendersky                             SourceMgr::DK_Error,
324e8b8f1bcSEli Bendersky                             "Can't back-reference more than 9 variables");
325e8b8f1bcSEli Bendersky             return true;
326e8b8f1bcSEli Bendersky           }
327e8b8f1bcSEli Bendersky           AddBackrefToRegEx(VarParenNum);
328e8b8f1bcSEli Bendersky         } else {
3298879e06dSChris Lattner           VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
330e8b8f1bcSEli Bendersky         }
3318879e06dSChris Lattner         continue;
3328879e06dSChris Lattner       }
3338879e06dSChris Lattner 
3348879e06dSChris Lattner       // Handle [[foo:.*]].
335e8b8f1bcSEli Bendersky       VariableDefs[Name] = CurParen;
3368879e06dSChris Lattner       RegExStr += '(';
3378879e06dSChris Lattner       ++CurParen;
3388879e06dSChris Lattner 
3398879e06dSChris Lattner       if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
3408879e06dSChris Lattner         return true;
3418879e06dSChris Lattner 
3428879e06dSChris Lattner       RegExStr += ')';
3438879e06dSChris Lattner     }
3448879e06dSChris Lattner 
3458879e06dSChris Lattner     // Handle fixed string matches.
3468879e06dSChris Lattner     // Find the end, which is the start of the next regex.
3478879e06dSChris Lattner     size_t FixedMatchEnd = PatternStr.find("{{");
3488879e06dSChris Lattner     FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
3496f4f77b7SHans Wennborg     RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
3508879e06dSChris Lattner     PatternStr = PatternStr.substr(FixedMatchEnd);
351f08d2db9SChris Lattner   }
352f08d2db9SChris Lattner 
35385913ccaSJames Y Knight   if (MatchFullLinesHere) {
35485913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
35585913ccaSJames Y Knight       RegExStr += " *";
35685913ccaSJames Y Knight     RegExStr += '$';
35785913ccaSJames Y Knight   }
35885913ccaSJames Y Knight 
35974d50731SChris Lattner   return false;
36074d50731SChris Lattner }
36174d50731SChris Lattner 
362e8b8f1bcSEli Bendersky bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen,
3638879e06dSChris Lattner                               SourceMgr &SM) {
364e8b8f1bcSEli Bendersky   Regex R(RS);
3658879e06dSChris Lattner   std::string Error;
3668879e06dSChris Lattner   if (!R.isValid(Error)) {
367e8b8f1bcSEli Bendersky     SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
36803b80a40SChris Lattner                     "invalid regex: " + Error);
3698879e06dSChris Lattner     return true;
3708879e06dSChris Lattner   }
3718879e06dSChris Lattner 
372e8b8f1bcSEli Bendersky   RegExStr += RS.str();
3738879e06dSChris Lattner   CurParen += R.getNumMatches();
3748879e06dSChris Lattner   return false;
3758879e06dSChris Lattner }
376b16ab0c4SChris Lattner 
377e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
378e8b8f1bcSEli Bendersky   assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
379e8b8f1bcSEli Bendersky   std::string Backref = std::string("\\") +
380e8b8f1bcSEli Bendersky                         std::string(1, '0' + BackrefNum);
381e8b8f1bcSEli Bendersky   RegExStr += Backref;
382e8b8f1bcSEli Bendersky }
383e8b8f1bcSEli Bendersky 
38492987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
38592987fb3SAlexander Kornienko   // The only supported expression is @LINE([\+-]\d+)?
38692987fb3SAlexander Kornienko   if (!Expr.startswith("@LINE"))
38792987fb3SAlexander Kornienko     return false;
38892987fb3SAlexander Kornienko   Expr = Expr.substr(StringRef("@LINE").size());
38992987fb3SAlexander Kornienko   int Offset = 0;
39092987fb3SAlexander Kornienko   if (!Expr.empty()) {
39192987fb3SAlexander Kornienko     if (Expr[0] == '+')
39292987fb3SAlexander Kornienko       Expr = Expr.substr(1);
39392987fb3SAlexander Kornienko     else if (Expr[0] != '-')
39492987fb3SAlexander Kornienko       return false;
39592987fb3SAlexander Kornienko     if (Expr.getAsInteger(10, Offset))
39692987fb3SAlexander Kornienko       return false;
39792987fb3SAlexander Kornienko   }
39892987fb3SAlexander Kornienko   Value = llvm::itostr(LineNumber + Offset);
39992987fb3SAlexander Kornienko   return true;
40092987fb3SAlexander Kornienko }
40192987fb3SAlexander Kornienko 
402f08d2db9SChris Lattner /// Match - Match the pattern string against the input buffer Buffer.  This
403f08d2db9SChris Lattner /// returns the position that is matched or npos if there is no match.  If
404f08d2db9SChris Lattner /// there is a match, the size of the matched string is returned in MatchLen.
4058879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
4068879e06dSChris Lattner                       StringMap<StringRef> &VariableTable) const {
407eba55822SJakob Stoklund Olesen   // If this is the EOF pattern, match it immediately.
40838820972SMatt Arsenault   if (CheckTy == Check::CheckEOF) {
409eba55822SJakob Stoklund Olesen     MatchLen = 0;
410eba55822SJakob Stoklund Olesen     return Buffer.size();
411eba55822SJakob Stoklund Olesen   }
412eba55822SJakob Stoklund Olesen 
413221460e0SChris Lattner   // If this is a fixed string pattern, just match it now.
414221460e0SChris Lattner   if (!FixedStr.empty()) {
415221460e0SChris Lattner     MatchLen = FixedStr.size();
416221460e0SChris Lattner     return Buffer.find(FixedStr);
417221460e0SChris Lattner   }
418221460e0SChris Lattner 
419b16ab0c4SChris Lattner   // Regex match.
4208879e06dSChris Lattner 
4218879e06dSChris Lattner   // If there are variable uses, we need to create a temporary string with the
4228879e06dSChris Lattner   // actual value.
4238879e06dSChris Lattner   StringRef RegExToMatch = RegExStr;
4248879e06dSChris Lattner   std::string TmpStr;
4258879e06dSChris Lattner   if (!VariableUses.empty()) {
4268879e06dSChris Lattner     TmpStr = RegExStr;
4278879e06dSChris Lattner 
4288879e06dSChris Lattner     unsigned InsertOffset = 0;
4298f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
43092987fb3SAlexander Kornienko       std::string Value;
43192987fb3SAlexander Kornienko 
4328f870499SBenjamin Kramer       if (VariableUse.first[0] == '@') {
4338f870499SBenjamin Kramer         if (!EvaluateExpression(VariableUse.first, Value))
43492987fb3SAlexander Kornienko           return StringRef::npos;
43592987fb3SAlexander Kornienko       } else {
436e0ef65abSDaniel Dunbar         StringMap<StringRef>::iterator it =
4378f870499SBenjamin Kramer             VariableTable.find(VariableUse.first);
438e0ef65abSDaniel Dunbar         // If the variable is undefined, return an error.
439e0ef65abSDaniel Dunbar         if (it == VariableTable.end())
440e0ef65abSDaniel Dunbar           return StringRef::npos;
441e0ef65abSDaniel Dunbar 
4426f4f77b7SHans Wennborg         // Look up the value and escape it so that we can put it into the regex.
4436f4f77b7SHans Wennborg         Value += Regex::escape(it->second);
44492987fb3SAlexander Kornienko       }
4458879e06dSChris Lattner 
4468879e06dSChris Lattner       // Plop it into the regex at the adjusted offset.
4478f870499SBenjamin Kramer       TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset,
4488879e06dSChris Lattner                     Value.begin(), Value.end());
4498879e06dSChris Lattner       InsertOffset += Value.size();
4508879e06dSChris Lattner     }
4518879e06dSChris Lattner 
4528879e06dSChris Lattner     // Match the newly constructed regex.
4538879e06dSChris Lattner     RegExToMatch = TmpStr;
4548879e06dSChris Lattner   }
4558879e06dSChris Lattner 
4568879e06dSChris Lattner 
457b16ab0c4SChris Lattner   SmallVector<StringRef, 4> MatchInfo;
4588879e06dSChris Lattner   if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
459f08d2db9SChris Lattner     return StringRef::npos;
460b16ab0c4SChris Lattner 
461b16ab0c4SChris Lattner   // Successful regex match.
462b16ab0c4SChris Lattner   assert(!MatchInfo.empty() && "Didn't get any match");
463b16ab0c4SChris Lattner   StringRef FullMatch = MatchInfo[0];
464b16ab0c4SChris Lattner 
4658879e06dSChris Lattner   // If this defines any variables, remember their values.
4668f870499SBenjamin Kramer   for (const auto &VariableDef : VariableDefs) {
4678f870499SBenjamin Kramer     assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
4688f870499SBenjamin Kramer     VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
4690a4c44bdSChris Lattner   }
4700a4c44bdSChris Lattner 
471b16ab0c4SChris Lattner   MatchLen = FullMatch.size();
472b16ab0c4SChris Lattner   return FullMatch.data()-Buffer.data();
473f08d2db9SChris Lattner }
474f08d2db9SChris Lattner 
475fd29d886SDaniel Dunbar unsigned Pattern::ComputeMatchDistance(StringRef Buffer,
476fd29d886SDaniel Dunbar                               const StringMap<StringRef> &VariableTable) const {
477fd29d886SDaniel Dunbar   // Just compute the number of matching characters. For regular expressions, we
478fd29d886SDaniel Dunbar   // just compare against the regex itself and hope for the best.
479fd29d886SDaniel Dunbar   //
480fd29d886SDaniel Dunbar   // FIXME: One easy improvement here is have the regex lib generate a single
481fd29d886SDaniel Dunbar   // example regular expression which matches, and use that as the example
482fd29d886SDaniel Dunbar   // string.
483fd29d886SDaniel Dunbar   StringRef ExampleString(FixedStr);
484fd29d886SDaniel Dunbar   if (ExampleString.empty())
485fd29d886SDaniel Dunbar     ExampleString = RegExStr;
486fd29d886SDaniel Dunbar 
487e9aa36c8SDaniel Dunbar   // Only compare up to the first line in the buffer, or the string size.
488e9aa36c8SDaniel Dunbar   StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
489e9aa36c8SDaniel Dunbar   BufferPrefix = BufferPrefix.split('\n').first;
490e9aa36c8SDaniel Dunbar   return BufferPrefix.edit_distance(ExampleString);
491fd29d886SDaniel Dunbar }
492fd29d886SDaniel Dunbar 
493e0ef65abSDaniel Dunbar void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
494e0ef65abSDaniel Dunbar                                const StringMap<StringRef> &VariableTable) const{
495e0ef65abSDaniel Dunbar   // If this was a regular expression using variables, print the current
496e0ef65abSDaniel Dunbar   // variable values.
497e0ef65abSDaniel Dunbar   if (!VariableUses.empty()) {
4988f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
499e69170a1SAlp Toker       SmallString<256> Msg;
500e69170a1SAlp Toker       raw_svector_ostream OS(Msg);
5018f870499SBenjamin Kramer       StringRef Var = VariableUse.first;
50292987fb3SAlexander Kornienko       if (Var[0] == '@') {
50392987fb3SAlexander Kornienko         std::string Value;
50492987fb3SAlexander Kornienko         if (EvaluateExpression(Var, Value)) {
50592987fb3SAlexander Kornienko           OS << "with expression \"";
50692987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\" equal to \"";
50792987fb3SAlexander Kornienko           OS.write_escaped(Value) << "\"";
50892987fb3SAlexander Kornienko         } else {
50992987fb3SAlexander Kornienko           OS << "uses incorrect expression \"";
51092987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
51192987fb3SAlexander Kornienko         }
51292987fb3SAlexander Kornienko       } else {
51392987fb3SAlexander Kornienko         StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
514e0ef65abSDaniel Dunbar 
515e0ef65abSDaniel Dunbar         // Check for undefined variable references.
516e0ef65abSDaniel Dunbar         if (it == VariableTable.end()) {
517e0ef65abSDaniel Dunbar           OS << "uses undefined variable \"";
51892987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
519e0ef65abSDaniel Dunbar         } else {
520e0ef65abSDaniel Dunbar           OS << "with variable \"";
521e0ef65abSDaniel Dunbar           OS.write_escaped(Var) << "\" equal to \"";
522e0ef65abSDaniel Dunbar           OS.write_escaped(it->second) << "\"";
523e0ef65abSDaniel Dunbar         }
52492987fb3SAlexander Kornienko       }
525e0ef65abSDaniel Dunbar 
52603b80a40SChris Lattner       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
52703b80a40SChris Lattner                       OS.str());
528e0ef65abSDaniel Dunbar     }
529e0ef65abSDaniel Dunbar   }
530fd29d886SDaniel Dunbar 
531fd29d886SDaniel Dunbar   // Attempt to find the closest/best fuzzy match.  Usually an error happens
532fd29d886SDaniel Dunbar   // because some string in the output didn't exactly match. In these cases, we
533fd29d886SDaniel Dunbar   // would like to show the user a best guess at what "should have" matched, to
534fd29d886SDaniel Dunbar   // save them having to actually check the input manually.
535fd29d886SDaniel Dunbar   size_t NumLinesForward = 0;
536fd29d886SDaniel Dunbar   size_t Best = StringRef::npos;
537fd29d886SDaniel Dunbar   double BestQuality = 0;
538fd29d886SDaniel Dunbar 
539fd29d886SDaniel Dunbar   // Use an arbitrary 4k limit on how far we will search.
5402bf486ebSDan Gohman   for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
541fd29d886SDaniel Dunbar     if (Buffer[i] == '\n')
542fd29d886SDaniel Dunbar       ++NumLinesForward;
543fd29d886SDaniel Dunbar 
544df22bbf7SDan Gohman     // Patterns have leading whitespace stripped, so skip whitespace when
545df22bbf7SDan Gohman     // looking for something which looks like a pattern.
546df22bbf7SDan Gohman     if (Buffer[i] == ' ' || Buffer[i] == '\t')
547df22bbf7SDan Gohman       continue;
548df22bbf7SDan Gohman 
549fd29d886SDaniel Dunbar     // Compute the "quality" of this match as an arbitrary combination of the
550fd29d886SDaniel Dunbar     // match distance and the number of lines skipped to get to this match.
551fd29d886SDaniel Dunbar     unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
552fd29d886SDaniel Dunbar     double Quality = Distance + (NumLinesForward / 100.);
553fd29d886SDaniel Dunbar 
554fd29d886SDaniel Dunbar     if (Quality < BestQuality || Best == StringRef::npos) {
555fd29d886SDaniel Dunbar       Best = i;
556fd29d886SDaniel Dunbar       BestQuality = Quality;
557fd29d886SDaniel Dunbar     }
558fd29d886SDaniel Dunbar   }
559fd29d886SDaniel Dunbar 
560fd29d886SDaniel Dunbar   // Print the "possible intended match here" line if we found something
561c069cc8eSDaniel Dunbar   // reasonable and not equal to what we showed in the "scanning from here"
562c069cc8eSDaniel Dunbar   // line.
563c069cc8eSDaniel Dunbar   if (Best && Best != StringRef::npos && BestQuality < 50) {
564fd29d886SDaniel Dunbar       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
56503b80a40SChris Lattner                       SourceMgr::DK_Note, "possible intended match here");
566fd29d886SDaniel Dunbar 
567fd29d886SDaniel Dunbar     // FIXME: If we wanted to be really friendly we would show why the match
568fd29d886SDaniel Dunbar     // failed, as it can be hard to spot simple one character differences.
569fd29d886SDaniel Dunbar   }
570e0ef65abSDaniel Dunbar }
57174d50731SChris Lattner 
57281e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
573061d2baaSEli Bendersky   // Offset keeps track of the current offset within the input Str
574061d2baaSEli Bendersky   size_t Offset = 0;
575061d2baaSEli Bendersky   // [...] Nesting depth
576061d2baaSEli Bendersky   size_t BracketDepth = 0;
577061d2baaSEli Bendersky 
578061d2baaSEli Bendersky   while (!Str.empty()) {
579061d2baaSEli Bendersky     if (Str.startswith("]]") && BracketDepth == 0)
580061d2baaSEli Bendersky       return Offset;
581061d2baaSEli Bendersky     if (Str[0] == '\\') {
582061d2baaSEli Bendersky       // Backslash escapes the next char within regexes, so skip them both.
583061d2baaSEli Bendersky       Str = Str.substr(2);
584061d2baaSEli Bendersky       Offset += 2;
585061d2baaSEli Bendersky     } else {
586061d2baaSEli Bendersky       switch (Str[0]) {
587061d2baaSEli Bendersky         default:
588061d2baaSEli Bendersky           break;
589061d2baaSEli Bendersky         case '[':
590061d2baaSEli Bendersky           BracketDepth++;
591061d2baaSEli Bendersky           break;
592061d2baaSEli Bendersky         case ']':
59381e5cd9eSAdrian Prantl           if (BracketDepth == 0) {
59481e5cd9eSAdrian Prantl             SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
59581e5cd9eSAdrian Prantl                             SourceMgr::DK_Error,
59681e5cd9eSAdrian Prantl                             "missing closing \"]\" for regex variable");
59781e5cd9eSAdrian Prantl             exit(1);
59881e5cd9eSAdrian Prantl           }
599061d2baaSEli Bendersky           BracketDepth--;
600061d2baaSEli Bendersky           break;
601061d2baaSEli Bendersky       }
602061d2baaSEli Bendersky       Str = Str.substr(1);
603061d2baaSEli Bendersky       Offset++;
604061d2baaSEli Bendersky     }
605061d2baaSEli Bendersky   }
606061d2baaSEli Bendersky 
607061d2baaSEli Bendersky   return StringRef::npos;
608061d2baaSEli Bendersky }
609061d2baaSEli Bendersky 
610061d2baaSEli Bendersky 
61174d50731SChris Lattner //===----------------------------------------------------------------------===//
61274d50731SChris Lattner // Check Strings.
61374d50731SChris Lattner //===----------------------------------------------------------------------===//
6143b40b445SChris Lattner 
6153b40b445SChris Lattner /// CheckString - This is a check that we found in the input file.
6163b40b445SChris Lattner struct CheckString {
6173b40b445SChris Lattner   /// Pat - The pattern to match.
6183b40b445SChris Lattner   Pattern Pat;
61926cccfe1SChris Lattner 
62013df4626SMatt Arsenault   /// Prefix - Which prefix name this check matched.
62113df4626SMatt Arsenault   StringRef Prefix;
62213df4626SMatt Arsenault 
62326cccfe1SChris Lattner   /// Loc - The location in the match file that the check string was specified.
62426cccfe1SChris Lattner   SMLoc Loc;
62526cccfe1SChris Lattner 
62638820972SMatt Arsenault   /// CheckTy - Specify what kind of check this is. e.g. CHECK-NEXT: directive,
62738820972SMatt Arsenault   /// as opposed to a CHECK: directive.
62885913ccaSJames Y Knight   //  Check::CheckType CheckTy;
629f8bd2e5bSStephen Lin 
63091a1b2c9SMichael Liao   /// DagNotStrings - These are all of the strings that are disallowed from
631236d2d5eSChris Lattner   /// occurring between this match string and the previous one (or start of
632236d2d5eSChris Lattner   /// file).
63391a1b2c9SMichael Liao   std::vector<Pattern> DagNotStrings;
634236d2d5eSChris Lattner 
63585913ccaSJames Y Knight   CheckString(const Pattern &P, StringRef S, SMLoc L)
63685913ccaSJames Y Knight       : Pat(P), Prefix(S), Loc(L) {}
637dcc7d48dSMichael Liao 
63891a1b2c9SMichael Liao   /// Check - Match check string and its "not strings" and/or "dag strings".
639e93a3a08SStephen Lin   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
640f8bd2e5bSStephen Lin                size_t &MatchLen, StringMap<StringRef> &VariableTable) const;
641dcc7d48dSMichael Liao 
642dcc7d48dSMichael Liao   /// CheckNext - Verify there is a single line in the given buffer.
643dcc7d48dSMichael Liao   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
644dcc7d48dSMichael Liao 
64501ac1707SDuncan P. N. Exon Smith   /// CheckSame - Verify there is no newline in the given buffer.
64601ac1707SDuncan P. N. Exon Smith   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
64701ac1707SDuncan P. N. Exon Smith 
648dcc7d48dSMichael Liao   /// CheckNot - Verify there's no "not strings" in the given buffer.
649dcc7d48dSMichael Liao   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
65091a1b2c9SMichael Liao                 const std::vector<const Pattern *> &NotStrings,
65191a1b2c9SMichael Liao                 StringMap<StringRef> &VariableTable) const;
65291a1b2c9SMichael Liao 
65391a1b2c9SMichael Liao   /// CheckDag - Match "dag strings" and their mixed "not strings".
65491a1b2c9SMichael Liao   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
65591a1b2c9SMichael Liao                   std::vector<const Pattern *> &NotStrings,
656dcc7d48dSMichael Liao                   StringMap<StringRef> &VariableTable) const;
65726cccfe1SChris Lattner };
65826cccfe1SChris Lattner 
6595ea04c38SGuy Benyei /// Canonicalize whitespaces in the input file. Line endings are replaced
6605ea04c38SGuy Benyei /// with UNIX-style '\n'.
6615ea04c38SGuy Benyei ///
6625ea04c38SGuy Benyei /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace
6635ea04c38SGuy Benyei /// characters to a single space.
6641961f14cSDavid Blaikie static std::unique_ptr<MemoryBuffer>
6651961f14cSDavid Blaikie CanonicalizeInputFile(std::unique_ptr<MemoryBuffer> MB,
6665ea04c38SGuy Benyei                       bool PreserveHorizontal) {
6670e45d24aSChris Lattner   SmallString<128> NewFile;
668a2f8fc5aSChris Lattner   NewFile.reserve(MB->getBufferSize());
669a2f8fc5aSChris Lattner 
670a2f8fc5aSChris Lattner   for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
671a2f8fc5aSChris Lattner        Ptr != End; ++Ptr) {
672fd781bf0SNAKAMURA Takumi     // Eliminate trailing dosish \r.
673fd781bf0SNAKAMURA Takumi     if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
674fd781bf0SNAKAMURA Takumi       continue;
675fd781bf0SNAKAMURA Takumi     }
676fd781bf0SNAKAMURA Takumi 
6775ea04c38SGuy Benyei     // If current char is not a horizontal whitespace or if horizontal
6785ea04c38SGuy Benyei     // whitespace canonicalization is disabled, dump it to output as is.
6795ea04c38SGuy Benyei     if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) {
680a2f8fc5aSChris Lattner       NewFile.push_back(*Ptr);
681a2f8fc5aSChris Lattner       continue;
682a2f8fc5aSChris Lattner     }
683a2f8fc5aSChris Lattner 
684a2f8fc5aSChris Lattner     // Otherwise, add one space and advance over neighboring space.
685a2f8fc5aSChris Lattner     NewFile.push_back(' ');
686a2f8fc5aSChris Lattner     while (Ptr+1 != End &&
687a2f8fc5aSChris Lattner            (Ptr[1] == ' ' || Ptr[1] == '\t'))
688a2f8fc5aSChris Lattner       ++Ptr;
689a2f8fc5aSChris Lattner   }
690a2f8fc5aSChris Lattner 
6911961f14cSDavid Blaikie   return std::unique_ptr<MemoryBuffer>(
6921961f14cSDavid Blaikie       MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()));
693a2f8fc5aSChris Lattner }
694a2f8fc5aSChris Lattner 
69538820972SMatt Arsenault static bool IsPartOfWord(char c) {
69638820972SMatt Arsenault   return (isalnum(c) || c == '-' || c == '_');
69738820972SMatt Arsenault }
69838820972SMatt Arsenault 
69913df4626SMatt Arsenault // Get the size of the prefix extension.
70013df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) {
70113df4626SMatt Arsenault   switch (Ty) {
70213df4626SMatt Arsenault   case Check::CheckNone:
703a908e7bdSPaul Robinson   case Check::CheckBadNot:
70413df4626SMatt Arsenault     return 0;
70513df4626SMatt Arsenault 
70613df4626SMatt Arsenault   case Check::CheckPlain:
70713df4626SMatt Arsenault     return sizeof(":") - 1;
70813df4626SMatt Arsenault 
70913df4626SMatt Arsenault   case Check::CheckNext:
71013df4626SMatt Arsenault     return sizeof("-NEXT:") - 1;
71113df4626SMatt Arsenault 
71201ac1707SDuncan P. N. Exon Smith   case Check::CheckSame:
71301ac1707SDuncan P. N. Exon Smith     return sizeof("-SAME:") - 1;
71401ac1707SDuncan P. N. Exon Smith 
71513df4626SMatt Arsenault   case Check::CheckNot:
71613df4626SMatt Arsenault     return sizeof("-NOT:") - 1;
71713df4626SMatt Arsenault 
71813df4626SMatt Arsenault   case Check::CheckDAG:
71913df4626SMatt Arsenault     return sizeof("-DAG:") - 1;
72013df4626SMatt Arsenault 
72113df4626SMatt Arsenault   case Check::CheckLabel:
72213df4626SMatt Arsenault     return sizeof("-LABEL:") - 1;
72313df4626SMatt Arsenault 
72413df4626SMatt Arsenault   case Check::CheckEOF:
72513df4626SMatt Arsenault     llvm_unreachable("Should not be using EOF size");
72613df4626SMatt Arsenault   }
72713df4626SMatt Arsenault 
72813df4626SMatt Arsenault   llvm_unreachable("Bad check type");
72913df4626SMatt Arsenault }
73013df4626SMatt Arsenault 
73113df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
732c4d2d471SMatt Arsenault   char NextChar = Buffer[Prefix.size()];
73338820972SMatt Arsenault 
73438820972SMatt Arsenault   // Verify that the : is present after the prefix.
73513df4626SMatt Arsenault   if (NextChar == ':')
73638820972SMatt Arsenault     return Check::CheckPlain;
73738820972SMatt Arsenault 
73813df4626SMatt Arsenault   if (NextChar != '-')
73938820972SMatt Arsenault     return Check::CheckNone;
74038820972SMatt Arsenault 
741c4d2d471SMatt Arsenault   StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
74213df4626SMatt Arsenault   if (Rest.startswith("NEXT:"))
74338820972SMatt Arsenault     return Check::CheckNext;
74438820972SMatt Arsenault 
74501ac1707SDuncan P. N. Exon Smith   if (Rest.startswith("SAME:"))
74601ac1707SDuncan P. N. Exon Smith     return Check::CheckSame;
74701ac1707SDuncan P. N. Exon Smith 
74813df4626SMatt Arsenault   if (Rest.startswith("NOT:"))
74938820972SMatt Arsenault     return Check::CheckNot;
75038820972SMatt Arsenault 
75113df4626SMatt Arsenault   if (Rest.startswith("DAG:"))
75238820972SMatt Arsenault     return Check::CheckDAG;
75338820972SMatt Arsenault 
75413df4626SMatt Arsenault   if (Rest.startswith("LABEL:"))
75538820972SMatt Arsenault     return Check::CheckLabel;
75613df4626SMatt Arsenault 
757a908e7bdSPaul Robinson   // You can't combine -NOT with another suffix.
758a908e7bdSPaul Robinson   if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
759a908e7bdSPaul Robinson       Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
760a908e7bdSPaul Robinson       Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:"))
761a908e7bdSPaul Robinson     return Check::CheckBadNot;
762a908e7bdSPaul Robinson 
76313df4626SMatt Arsenault   return Check::CheckNone;
76438820972SMatt Arsenault }
76538820972SMatt Arsenault 
76613df4626SMatt Arsenault // From the given position, find the next character after the word.
76713df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) {
76813df4626SMatt Arsenault   while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
76913df4626SMatt Arsenault     ++Loc;
77013df4626SMatt Arsenault   return Loc;
77113df4626SMatt Arsenault }
77213df4626SMatt Arsenault 
77313df4626SMatt Arsenault // Try to find the first match in buffer for any prefix. If a valid match is
77413df4626SMatt Arsenault // found, return that prefix and set its type and location.  If there are almost
77513df4626SMatt Arsenault // matches (e.g. the actual prefix string is found, but is not an actual check
77613df4626SMatt Arsenault // string), but no valid match, return an empty string and set the position to
77713df4626SMatt Arsenault // resume searching from. If no partial matches are found, return an empty
77813df4626SMatt Arsenault // string and the location will be StringRef::npos. If one prefix is a substring
77913df4626SMatt Arsenault // of another, the maximal match should be found. e.g. if "A" and "AA" are
78013df4626SMatt Arsenault // prefixes then AA-CHECK: should match the second one.
78113df4626SMatt Arsenault static StringRef FindFirstCandidateMatch(StringRef &Buffer,
78213df4626SMatt Arsenault                                          Check::CheckType &CheckTy,
78313df4626SMatt Arsenault                                          size_t &CheckLoc) {
78413df4626SMatt Arsenault   StringRef FirstPrefix;
78513df4626SMatt Arsenault   size_t FirstLoc = StringRef::npos;
78613df4626SMatt Arsenault   size_t SearchLoc = StringRef::npos;
78713df4626SMatt Arsenault   Check::CheckType FirstTy = Check::CheckNone;
78813df4626SMatt Arsenault 
78913df4626SMatt Arsenault   CheckTy = Check::CheckNone;
79013df4626SMatt Arsenault   CheckLoc = StringRef::npos;
79113df4626SMatt Arsenault 
7928f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
79313df4626SMatt Arsenault     size_t PrefixLoc = Buffer.find(Prefix);
79413df4626SMatt Arsenault 
79513df4626SMatt Arsenault     if (PrefixLoc == StringRef::npos)
79613df4626SMatt Arsenault       continue;
79713df4626SMatt Arsenault 
79813df4626SMatt Arsenault     // Track where we are searching for invalid prefixes that look almost right.
79913df4626SMatt Arsenault     // We need to only advance to the first partial match on the next attempt
80013df4626SMatt Arsenault     // since a partial match could be a substring of a later, valid prefix.
80113df4626SMatt Arsenault     // Need to skip to the end of the word, otherwise we could end up
80213df4626SMatt Arsenault     // matching a prefix in a substring later.
80313df4626SMatt Arsenault     if (PrefixLoc < SearchLoc)
80413df4626SMatt Arsenault       SearchLoc = SkipWord(Buffer, PrefixLoc);
80513df4626SMatt Arsenault 
80613df4626SMatt Arsenault     // We only want to find the first match to avoid skipping some.
80713df4626SMatt Arsenault     if (PrefixLoc > FirstLoc)
80813df4626SMatt Arsenault       continue;
809a7181a1bSAlexey Samsonov     // If one matching check-prefix is a prefix of another, choose the
810a7181a1bSAlexey Samsonov     // longer one.
811a7181a1bSAlexey Samsonov     if (PrefixLoc == FirstLoc && Prefix.size() < FirstPrefix.size())
812a7181a1bSAlexey Samsonov       continue;
81313df4626SMatt Arsenault 
81413df4626SMatt Arsenault     StringRef Rest = Buffer.drop_front(PrefixLoc);
81513df4626SMatt Arsenault     // Make sure we have actually found the prefix, and not a word containing
81613df4626SMatt Arsenault     // it. This should also prevent matching the wrong prefix when one is a
81713df4626SMatt Arsenault     // substring of another.
81813df4626SMatt Arsenault     if (PrefixLoc != 0 && IsPartOfWord(Buffer[PrefixLoc - 1]))
81943b5f572SDaniel Sanders       FirstTy = Check::CheckNone;
82043b5f572SDaniel Sanders     else
82143b5f572SDaniel Sanders       FirstTy = FindCheckType(Rest, Prefix);
82213df4626SMatt Arsenault 
82313df4626SMatt Arsenault     FirstLoc = PrefixLoc;
824a7181a1bSAlexey Samsonov     FirstPrefix = Prefix;
82513df4626SMatt Arsenault   }
82613df4626SMatt Arsenault 
827a7181a1bSAlexey Samsonov   // If the first prefix is invalid, we should continue the search after it.
828a7181a1bSAlexey Samsonov   if (FirstTy == Check::CheckNone) {
82913df4626SMatt Arsenault     CheckLoc = SearchLoc;
830a7181a1bSAlexey Samsonov     return "";
831a7181a1bSAlexey Samsonov   }
832a7181a1bSAlexey Samsonov 
83313df4626SMatt Arsenault   CheckTy = FirstTy;
83413df4626SMatt Arsenault   CheckLoc = FirstLoc;
83513df4626SMatt Arsenault   return FirstPrefix;
83613df4626SMatt Arsenault }
83713df4626SMatt Arsenault 
83813df4626SMatt Arsenault static StringRef FindFirstMatchingPrefix(StringRef &Buffer,
83913df4626SMatt Arsenault                                          unsigned &LineNumber,
84013df4626SMatt Arsenault                                          Check::CheckType &CheckTy,
84113df4626SMatt Arsenault                                          size_t &CheckLoc) {
84213df4626SMatt Arsenault   while (!Buffer.empty()) {
84313df4626SMatt Arsenault     StringRef Prefix = FindFirstCandidateMatch(Buffer, CheckTy, CheckLoc);
84413df4626SMatt Arsenault     // If we found a real match, we are done.
84513df4626SMatt Arsenault     if (!Prefix.empty()) {
84613df4626SMatt Arsenault       LineNumber += Buffer.substr(0, CheckLoc).count('\n');
84713df4626SMatt Arsenault       return Prefix;
84813df4626SMatt Arsenault     }
84913df4626SMatt Arsenault 
85013df4626SMatt Arsenault     // We didn't find any almost matches either, we are also done.
85113df4626SMatt Arsenault     if (CheckLoc == StringRef::npos)
85213df4626SMatt Arsenault       return StringRef();
85313df4626SMatt Arsenault 
85413df4626SMatt Arsenault     LineNumber += Buffer.substr(0, CheckLoc + 1).count('\n');
85513df4626SMatt Arsenault 
85613df4626SMatt Arsenault     // Advance to the last possible match we found and try again.
85713df4626SMatt Arsenault     Buffer = Buffer.drop_front(CheckLoc + 1);
85813df4626SMatt Arsenault   }
85913df4626SMatt Arsenault 
86013df4626SMatt Arsenault   return StringRef();
86138820972SMatt Arsenault }
862ee3c74fbSChris Lattner 
863ee3c74fbSChris Lattner /// ReadCheckFile - Read the check file, which specifies the sequence of
864ee3c74fbSChris Lattner /// expected strings.  The strings are added to the CheckStrings vector.
86543d50d4aSEli Bendersky /// Returns true in case of an error, false otherwise.
866ee3c74fbSChris Lattner static bool ReadCheckFile(SourceMgr &SM,
86726cccfe1SChris Lattner                           std::vector<CheckString> &CheckStrings) {
868adf21f2aSRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
869adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(CheckFilename);
870adf21f2aSRafael Espindola   if (std::error_code EC = FileOrErr.getError()) {
871adf21f2aSRafael Espindola     errs() << "Could not open check file '" << CheckFilename
872adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
873ee3c74fbSChris Lattner     return true;
874ee3c74fbSChris Lattner   }
875a2f8fc5aSChris Lattner 
876a2f8fc5aSChris Lattner   // If we want to canonicalize whitespace, strip excess whitespace from the
8775ea04c38SGuy Benyei   // buffer containing the CHECK lines. Remove DOS style line endings.
8783560ff2cSRafael Espindola   std::unique_ptr<MemoryBuffer> F = CanonicalizeInputFile(
8793560ff2cSRafael Espindola       std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace);
880ee3c74fbSChris Lattner 
88110f10cedSChris Lattner   // Find all instances of CheckPrefix followed by : in the file.
882caa5fc0cSChris Lattner   StringRef Buffer = F->getBuffer();
88356ccdbbdSAlexander Kornienko 
8841961f14cSDavid Blaikie   SM.AddNewSourceBuffer(std::move(F), SMLoc());
8851961f14cSDavid Blaikie 
88656ccdbbdSAlexander Kornienko   std::vector<Pattern> ImplicitNegativeChecks;
88756ccdbbdSAlexander Kornienko   for (const auto &PatternString : ImplicitCheckNot) {
88856ccdbbdSAlexander Kornienko     // Create a buffer with fake command line content in order to display the
88956ccdbbdSAlexander Kornienko     // command line option responsible for the specific implicit CHECK-NOT.
890ff43d69dSDavid Blaikie     std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str();
89156ccdbbdSAlexander Kornienko     std::string Suffix = "'";
8923560ff2cSRafael Espindola     std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
8933560ff2cSRafael Espindola         Prefix + PatternString + Suffix, "command line");
8943560ff2cSRafael Espindola 
89556ccdbbdSAlexander Kornienko     StringRef PatternInBuffer =
89656ccdbbdSAlexander Kornienko         CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
8971961f14cSDavid Blaikie     SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
89856ccdbbdSAlexander Kornienko 
89956ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot));
90056ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
90156ccdbbdSAlexander Kornienko                                                "IMPLICIT-CHECK", SM, 0);
90256ccdbbdSAlexander Kornienko   }
90356ccdbbdSAlexander Kornienko 
90456ccdbbdSAlexander Kornienko 
90556ccdbbdSAlexander Kornienko   std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
906236d2d5eSChris Lattner 
90743d50d4aSEli Bendersky   // LineNumber keeps track of the line on which CheckPrefix instances are
90843d50d4aSEli Bendersky   // found.
90992987fb3SAlexander Kornienko   unsigned LineNumber = 1;
91092987fb3SAlexander Kornienko 
911ee3c74fbSChris Lattner   while (1) {
91213df4626SMatt Arsenault     Check::CheckType CheckTy;
91313df4626SMatt Arsenault     size_t PrefixLoc;
91413df4626SMatt Arsenault 
91513df4626SMatt Arsenault     // See if a prefix occurs in the memory buffer.
91613df4626SMatt Arsenault     StringRef UsedPrefix = FindFirstMatchingPrefix(Buffer,
91713df4626SMatt Arsenault                                                    LineNumber,
91813df4626SMatt Arsenault                                                    CheckTy,
91913df4626SMatt Arsenault                                                    PrefixLoc);
92013df4626SMatt Arsenault     if (UsedPrefix.empty())
921ee3c74fbSChris Lattner       break;
922ee3c74fbSChris Lattner 
92313df4626SMatt Arsenault     Buffer = Buffer.drop_front(PrefixLoc);
92492987fb3SAlexander Kornienko 
92513df4626SMatt Arsenault     // Location to use for error messages.
92613df4626SMatt Arsenault     const char *UsedPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1);
92792987fb3SAlexander Kornienko 
92813df4626SMatt Arsenault     // PrefixLoc is to the start of the prefix. Skip to the end.
92913df4626SMatt Arsenault     Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
93010f10cedSChris Lattner 
931a908e7bdSPaul Robinson     // Complain about useful-looking but unsupported suffixes.
932a908e7bdSPaul Robinson     if (CheckTy == Check::CheckBadNot) {
933a908e7bdSPaul Robinson       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
934a908e7bdSPaul Robinson                       SourceMgr::DK_Error,
935a908e7bdSPaul Robinson                       "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
936a908e7bdSPaul Robinson       return true;
937a908e7bdSPaul Robinson     }
938a908e7bdSPaul Robinson 
93938820972SMatt Arsenault     // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
94038820972SMatt Arsenault     // leading and trailing whitespace.
941236d2d5eSChris Lattner     Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
942ee3c74fbSChris Lattner 
943ee3c74fbSChris Lattner     // Scan ahead to the end of line.
944caa5fc0cSChris Lattner     size_t EOL = Buffer.find_first_of("\n\r");
945ee3c74fbSChris Lattner 
946838fb09aSDan Gohman     // Remember the location of the start of the pattern, for diagnostics.
947838fb09aSDan Gohman     SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
948838fb09aSDan Gohman 
94974d50731SChris Lattner     // Parse the pattern.
95038820972SMatt Arsenault     Pattern P(CheckTy);
95113df4626SMatt Arsenault     if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber))
952ee3c74fbSChris Lattner       return true;
953ee3c74fbSChris Lattner 
954f8bd2e5bSStephen Lin     // Verify that CHECK-LABEL lines do not define or use variables
95538820972SMatt Arsenault     if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
95613df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
957f8bd2e5bSStephen Lin                       SourceMgr::DK_Error,
95813df4626SMatt Arsenault                       "found '" + UsedPrefix + "-LABEL:'"
95913df4626SMatt Arsenault                       " with variable definition or use");
960f8bd2e5bSStephen Lin       return true;
961f8bd2e5bSStephen Lin     }
962f8bd2e5bSStephen Lin 
963236d2d5eSChris Lattner     Buffer = Buffer.substr(EOL);
96474d50731SChris Lattner 
965da108b4eSChris Lattner     // Verify that CHECK-NEXT lines have at least one CHECK line before them.
96601ac1707SDuncan P. N. Exon Smith     if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
96701ac1707SDuncan P. N. Exon Smith         CheckStrings.empty()) {
96801ac1707SDuncan P. N. Exon Smith       StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
96913df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
97003b80a40SChris Lattner                       SourceMgr::DK_Error,
97101ac1707SDuncan P. N. Exon Smith                       "found '" + UsedPrefix + "-" + Type + "' without previous '"
97213df4626SMatt Arsenault                       + UsedPrefix + ": line");
973da108b4eSChris Lattner       return true;
974da108b4eSChris Lattner     }
975da108b4eSChris Lattner 
97691a1b2c9SMichael Liao     // Handle CHECK-DAG/-NOT.
97738820972SMatt Arsenault     if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
97891a1b2c9SMichael Liao       DagNotMatches.push_back(P);
97974d50731SChris Lattner       continue;
98074d50731SChris Lattner     }
98174d50731SChris Lattner 
982ee3c74fbSChris Lattner     // Okay, add the string we captured to the output vector and move on.
98385913ccaSJames Y Knight     CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
98491a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
98556ccdbbdSAlexander Kornienko     DagNotMatches = ImplicitNegativeChecks;
986ee3c74fbSChris Lattner   }
987ee3c74fbSChris Lattner 
98813df4626SMatt Arsenault   // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
98913df4626SMatt Arsenault   // prefix as a filler for the error message.
99091a1b2c9SMichael Liao   if (!DagNotMatches.empty()) {
991f5e2fc47SBenjamin Kramer     CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(),
99285913ccaSJames Y Knight                               SMLoc::getFromPointer(Buffer.data()));
99391a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
994eba55822SJakob Stoklund Olesen   }
995eba55822SJakob Stoklund Olesen 
996ee3c74fbSChris Lattner   if (CheckStrings.empty()) {
99713df4626SMatt Arsenault     errs() << "error: no check strings found with prefix"
99813df4626SMatt Arsenault            << (CheckPrefixes.size() > 1 ? "es " : " ");
9993e3ef2f2SChris Bieneman     prefix_iterator I = CheckPrefixes.begin();
10003e3ef2f2SChris Bieneman     prefix_iterator E = CheckPrefixes.end();
10013e3ef2f2SChris Bieneman     if (I != E) {
10023e3ef2f2SChris Bieneman       errs() << "\'" << *I << ":'";
10033e3ef2f2SChris Bieneman       ++I;
100413df4626SMatt Arsenault     }
10053e3ef2f2SChris Bieneman     for (; I != E; ++I)
10063e3ef2f2SChris Bieneman       errs() << ", \'" << *I << ":'";
100713df4626SMatt Arsenault 
100813df4626SMatt Arsenault     errs() << '\n';
1009ee3c74fbSChris Lattner     return true;
1010ee3c74fbSChris Lattner   }
1011ee3c74fbSChris Lattner 
1012ee3c74fbSChris Lattner   return false;
1013ee3c74fbSChris Lattner }
1014ee3c74fbSChris Lattner 
10153c76c523SCraig Topper static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc,
101691a1b2c9SMichael Liao                              const Pattern &Pat, StringRef Buffer,
1017e0ef65abSDaniel Dunbar                              StringMap<StringRef> &VariableTable) {
1018da108b4eSChris Lattner   // Otherwise, we have an error, emit an error message.
101991a1b2c9SMichael Liao   SM.PrintMessage(Loc, SourceMgr::DK_Error,
102003b80a40SChris Lattner                   "expected string not found in input");
1021da108b4eSChris Lattner 
1022da108b4eSChris Lattner   // Print the "scanning from here" line.  If the current position is at the
1023da108b4eSChris Lattner   // end of a line, advance to the start of the next line.
1024caa5fc0cSChris Lattner   Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
1025da108b4eSChris Lattner 
102603b80a40SChris Lattner   SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
102703b80a40SChris Lattner                   "scanning from here");
1028e0ef65abSDaniel Dunbar 
1029e0ef65abSDaniel Dunbar   // Allow the pattern to print additional information if desired.
103091a1b2c9SMichael Liao   Pat.PrintFailureInfo(SM, Buffer, VariableTable);
103191a1b2c9SMichael Liao }
103291a1b2c9SMichael Liao 
103391a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
103491a1b2c9SMichael Liao                              StringRef Buffer,
103591a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) {
103691a1b2c9SMichael Liao   PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
1037da108b4eSChris Lattner }
1038da108b4eSChris Lattner 
103937183584SChris Lattner /// CountNumNewlinesBetween - Count the number of newlines in the specified
104037183584SChris Lattner /// range.
1041592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range,
1042592fe880SRichard Smith                                         const char *&FirstNewLine) {
1043da108b4eSChris Lattner   unsigned NumNewLines = 0;
104437183584SChris Lattner   while (1) {
1045da108b4eSChris Lattner     // Scan for newline.
104637183584SChris Lattner     Range = Range.substr(Range.find_first_of("\n\r"));
104737183584SChris Lattner     if (Range.empty()) return NumNewLines;
1048da108b4eSChris Lattner 
1049da108b4eSChris Lattner     ++NumNewLines;
1050da108b4eSChris Lattner 
1051da108b4eSChris Lattner     // Handle \n\r and \r\n as a single newline.
105237183584SChris Lattner     if (Range.size() > 1 &&
105337183584SChris Lattner         (Range[1] == '\n' || Range[1] == '\r') &&
105437183584SChris Lattner         (Range[0] != Range[1]))
105537183584SChris Lattner       Range = Range.substr(1);
105637183584SChris Lattner     Range = Range.substr(1);
1057592fe880SRichard Smith 
1058592fe880SRichard Smith     if (NumNewLines == 1)
1059592fe880SRichard Smith       FirstNewLine = Range.begin();
1060da108b4eSChris Lattner   }
1061da108b4eSChris Lattner }
1062da108b4eSChris Lattner 
1063dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
1064e93a3a08SStephen Lin                           bool IsLabelScanMode, size_t &MatchLen,
1065dcc7d48dSMichael Liao                           StringMap<StringRef> &VariableTable) const {
106691a1b2c9SMichael Liao   size_t LastPos = 0;
106791a1b2c9SMichael Liao   std::vector<const Pattern *> NotStrings;
106891a1b2c9SMichael Liao 
1069e93a3a08SStephen Lin   // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1070e93a3a08SStephen Lin   // bounds; we have not processed variable definitions within the bounded block
1071e93a3a08SStephen Lin   // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1072e93a3a08SStephen Lin   // over the block again (including the last CHECK-LABEL) in normal mode.
1073e93a3a08SStephen Lin   if (!IsLabelScanMode) {
107491a1b2c9SMichael Liao     // Match "dag strings" (with mixed "not strings" if any).
107591a1b2c9SMichael Liao     LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable);
107691a1b2c9SMichael Liao     if (LastPos == StringRef::npos)
107791a1b2c9SMichael Liao       return StringRef::npos;
1078e93a3a08SStephen Lin   }
107991a1b2c9SMichael Liao 
108091a1b2c9SMichael Liao   // Match itself from the last position after matching CHECK-DAG.
108191a1b2c9SMichael Liao   StringRef MatchBuffer = Buffer.substr(LastPos);
108291a1b2c9SMichael Liao   size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
1083dcc7d48dSMichael Liao   if (MatchPos == StringRef::npos) {
108491a1b2c9SMichael Liao     PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
1085dcc7d48dSMichael Liao     return StringRef::npos;
1086dcc7d48dSMichael Liao   }
1087dcc7d48dSMichael Liao 
1088e93a3a08SStephen Lin   // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1089e93a3a08SStephen Lin   // or CHECK-NOT
1090e93a3a08SStephen Lin   if (!IsLabelScanMode) {
109191a1b2c9SMichael Liao     StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1092dcc7d48dSMichael Liao 
1093dcc7d48dSMichael Liao     // If this check is a "CHECK-NEXT", verify that the previous match was on
1094dcc7d48dSMichael Liao     // the previous line (i.e. that there is one newline between them).
1095dcc7d48dSMichael Liao     if (CheckNext(SM, SkippedRegion))
1096dcc7d48dSMichael Liao       return StringRef::npos;
1097dcc7d48dSMichael Liao 
109801ac1707SDuncan P. N. Exon Smith     // If this check is a "CHECK-SAME", verify that the previous match was on
109901ac1707SDuncan P. N. Exon Smith     // the same line (i.e. that there is no newline between them).
110001ac1707SDuncan P. N. Exon Smith     if (CheckSame(SM, SkippedRegion))
110101ac1707SDuncan P. N. Exon Smith       return StringRef::npos;
110201ac1707SDuncan P. N. Exon Smith 
1103dcc7d48dSMichael Liao     // If this match had "not strings", verify that they don't exist in the
1104dcc7d48dSMichael Liao     // skipped region.
110591a1b2c9SMichael Liao     if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
1106dcc7d48dSMichael Liao       return StringRef::npos;
1107f8bd2e5bSStephen Lin   }
1108dcc7d48dSMichael Liao 
11097dfb92b9SMehdi Amini   return LastPos + MatchPos;
1110dcc7d48dSMichael Liao }
1111dcc7d48dSMichael Liao 
1112dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
111385913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckNext)
1114dcc7d48dSMichael Liao     return false;
1115dcc7d48dSMichael Liao 
1116dcc7d48dSMichael Liao   // Count the number of newlines between the previous match and this one.
1117dcc7d48dSMichael Liao   assert(Buffer.data() !=
1118dcc7d48dSMichael Liao          SM.getMemoryBuffer(
1119dcc7d48dSMichael Liao            SM.FindBufferContainingLoc(
1120dcc7d48dSMichael Liao              SMLoc::getFromPointer(Buffer.data())))->getBufferStart() &&
1121dcc7d48dSMichael Liao          "CHECK-NEXT can't be the first check in a file");
1122dcc7d48dSMichael Liao 
112366f09ad0SCraig Topper   const char *FirstNewLine = nullptr;
1124592fe880SRichard Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1125dcc7d48dSMichael Liao 
1126dcc7d48dSMichael Liao   if (NumNewLines == 0) {
112713df4626SMatt Arsenault     SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix +
1128dcc7d48dSMichael Liao                     "-NEXT: is on the same line as previous match");
1129dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
1130dcc7d48dSMichael Liao                     SourceMgr::DK_Note, "'next' match was here");
1131dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1132dcc7d48dSMichael Liao                     "previous match ended here");
1133dcc7d48dSMichael Liao     return true;
1134dcc7d48dSMichael Liao   }
1135dcc7d48dSMichael Liao 
1136dcc7d48dSMichael Liao   if (NumNewLines != 1) {
113713df4626SMatt Arsenault     SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix +
1138dcc7d48dSMichael Liao                     "-NEXT: is not on the line after the previous match");
1139dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
1140dcc7d48dSMichael Liao                     SourceMgr::DK_Note, "'next' match was here");
1141dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1142dcc7d48dSMichael Liao                     "previous match ended here");
1143592fe880SRichard Smith     SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
1144592fe880SRichard Smith                     "non-matching line after previous match is here");
1145dcc7d48dSMichael Liao     return true;
1146dcc7d48dSMichael Liao   }
1147dcc7d48dSMichael Liao 
1148dcc7d48dSMichael Liao   return false;
1149dcc7d48dSMichael Liao }
1150dcc7d48dSMichael Liao 
115101ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
115285913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckSame)
115301ac1707SDuncan P. N. Exon Smith     return false;
115401ac1707SDuncan P. N. Exon Smith 
115501ac1707SDuncan P. N. Exon Smith   // Count the number of newlines between the previous match and this one.
115601ac1707SDuncan P. N. Exon Smith   assert(Buffer.data() !=
115701ac1707SDuncan P. N. Exon Smith              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
115801ac1707SDuncan P. N. Exon Smith                                     SMLoc::getFromPointer(Buffer.data())))
115901ac1707SDuncan P. N. Exon Smith                  ->getBufferStart() &&
116001ac1707SDuncan P. N. Exon Smith          "CHECK-SAME can't be the first check in a file");
116101ac1707SDuncan P. N. Exon Smith 
116201ac1707SDuncan P. N. Exon Smith   const char *FirstNewLine = nullptr;
116301ac1707SDuncan P. N. Exon Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
116401ac1707SDuncan P. N. Exon Smith 
116501ac1707SDuncan P. N. Exon Smith   if (NumNewLines != 0) {
116601ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(Loc, SourceMgr::DK_Error,
116701ac1707SDuncan P. N. Exon Smith                     Prefix +
116801ac1707SDuncan P. N. Exon Smith                         "-SAME: is not on the same line as the previous match");
116901ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
117001ac1707SDuncan P. N. Exon Smith                     "'next' match was here");
117101ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
117201ac1707SDuncan P. N. Exon Smith                     "previous match ended here");
117301ac1707SDuncan P. N. Exon Smith     return true;
117401ac1707SDuncan P. N. Exon Smith   }
117501ac1707SDuncan P. N. Exon Smith 
117601ac1707SDuncan P. N. Exon Smith   return false;
117701ac1707SDuncan P. N. Exon Smith }
117801ac1707SDuncan P. N. Exon Smith 
1179dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
118091a1b2c9SMichael Liao                            const std::vector<const Pattern *> &NotStrings,
1181dcc7d48dSMichael Liao                            StringMap<StringRef> &VariableTable) const {
11828f870499SBenjamin Kramer   for (const Pattern *Pat : NotStrings) {
118338820972SMatt Arsenault     assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
118491a1b2c9SMichael Liao 
1185dcc7d48dSMichael Liao     size_t MatchLen = 0;
118691a1b2c9SMichael Liao     size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
1187dcc7d48dSMichael Liao 
1188dcc7d48dSMichael Liao     if (Pos == StringRef::npos) continue;
1189dcc7d48dSMichael Liao 
1190dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos),
1191dcc7d48dSMichael Liao                     SourceMgr::DK_Error,
119213df4626SMatt Arsenault                     Prefix + "-NOT: string occurred!");
119391a1b2c9SMichael Liao     SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
119413df4626SMatt Arsenault                     Prefix + "-NOT: pattern specified here");
1195dcc7d48dSMichael Liao     return true;
1196dcc7d48dSMichael Liao   }
1197dcc7d48dSMichael Liao 
1198dcc7d48dSMichael Liao   return false;
1199dcc7d48dSMichael Liao }
1200dcc7d48dSMichael Liao 
120191a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
120291a1b2c9SMichael Liao                              std::vector<const Pattern *> &NotStrings,
120391a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) const {
120491a1b2c9SMichael Liao   if (DagNotStrings.empty())
120591a1b2c9SMichael Liao     return 0;
120691a1b2c9SMichael Liao 
120791a1b2c9SMichael Liao   size_t LastPos = 0;
120891a1b2c9SMichael Liao   size_t StartPos = LastPos;
120991a1b2c9SMichael Liao 
12108f870499SBenjamin Kramer   for (const Pattern &Pat : DagNotStrings) {
121138820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG ||
121238820972SMatt Arsenault             Pat.getCheckTy() == Check::CheckNot) &&
121391a1b2c9SMichael Liao            "Invalid CHECK-DAG or CHECK-NOT!");
121491a1b2c9SMichael Liao 
121538820972SMatt Arsenault     if (Pat.getCheckTy() == Check::CheckNot) {
121691a1b2c9SMichael Liao       NotStrings.push_back(&Pat);
121791a1b2c9SMichael Liao       continue;
121891a1b2c9SMichael Liao     }
121991a1b2c9SMichael Liao 
122038820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
122191a1b2c9SMichael Liao 
122291a1b2c9SMichael Liao     size_t MatchLen = 0, MatchPos;
122391a1b2c9SMichael Liao 
122491a1b2c9SMichael Liao     // CHECK-DAG always matches from the start.
122591a1b2c9SMichael Liao     StringRef MatchBuffer = Buffer.substr(StartPos);
122691a1b2c9SMichael Liao     MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
122791a1b2c9SMichael Liao     // With a group of CHECK-DAGs, a single mismatching means the match on
122891a1b2c9SMichael Liao     // that group of CHECK-DAGs fails immediately.
122991a1b2c9SMichael Liao     if (MatchPos == StringRef::npos) {
123091a1b2c9SMichael Liao       PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
123191a1b2c9SMichael Liao       return StringRef::npos;
123291a1b2c9SMichael Liao     }
123391a1b2c9SMichael Liao     // Re-calc it as the offset relative to the start of the original string.
123491a1b2c9SMichael Liao     MatchPos += StartPos;
123591a1b2c9SMichael Liao 
123691a1b2c9SMichael Liao     if (!NotStrings.empty()) {
123791a1b2c9SMichael Liao       if (MatchPos < LastPos) {
123891a1b2c9SMichael Liao         // Reordered?
123991a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
124091a1b2c9SMichael Liao                         SourceMgr::DK_Error,
124113df4626SMatt Arsenault                         Prefix + "-DAG: found a match of CHECK-DAG"
124291a1b2c9SMichael Liao                         " reordering across a CHECK-NOT");
124391a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
124491a1b2c9SMichael Liao                         SourceMgr::DK_Note,
124513df4626SMatt Arsenault                         Prefix + "-DAG: the farthest match of CHECK-DAG"
124691a1b2c9SMichael Liao                         " is found here");
124791a1b2c9SMichael Liao         SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
124813df4626SMatt Arsenault                         Prefix + "-NOT: the crossed pattern specified"
124991a1b2c9SMichael Liao                         " here");
125091a1b2c9SMichael Liao         SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
125113df4626SMatt Arsenault                         Prefix + "-DAG: the reordered pattern specified"
125291a1b2c9SMichael Liao                         " here");
125391a1b2c9SMichael Liao         return StringRef::npos;
125491a1b2c9SMichael Liao       }
125591a1b2c9SMichael Liao       // All subsequent CHECK-DAGs should be matched from the farthest
125691a1b2c9SMichael Liao       // position of all precedent CHECK-DAGs (including this one.)
125791a1b2c9SMichael Liao       StartPos = LastPos;
125891a1b2c9SMichael Liao       // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
125991a1b2c9SMichael Liao       // CHECK-DAG, verify that there's no 'not' strings occurred in that
126091a1b2c9SMichael Liao       // region.
126191a1b2c9SMichael Liao       StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1262cf708c32STim Northover       if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
126391a1b2c9SMichael Liao         return StringRef::npos;
126491a1b2c9SMichael Liao       // Clear "not strings".
126591a1b2c9SMichael Liao       NotStrings.clear();
126691a1b2c9SMichael Liao     }
126791a1b2c9SMichael Liao 
126891a1b2c9SMichael Liao     // Update the last position with CHECK-DAG matches.
126991a1b2c9SMichael Liao     LastPos = std::max(MatchPos + MatchLen, LastPos);
127091a1b2c9SMichael Liao   }
127191a1b2c9SMichael Liao 
127291a1b2c9SMichael Liao   return LastPos;
127391a1b2c9SMichael Liao }
127491a1b2c9SMichael Liao 
127513df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores.
127613df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) {
127713df4626SMatt Arsenault   Regex Validator("^[a-zA-Z0-9_-]*$");
127813df4626SMatt Arsenault   return Validator.match(CheckPrefix);
127913df4626SMatt Arsenault }
128013df4626SMatt Arsenault 
128113df4626SMatt Arsenault static bool ValidateCheckPrefixes() {
128213df4626SMatt Arsenault   StringSet<> PrefixSet;
128313df4626SMatt Arsenault 
12848f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
128524412b14SEli Bendersky     // Reject empty prefixes.
128624412b14SEli Bendersky     if (Prefix == "")
128724412b14SEli Bendersky       return false;
128824412b14SEli Bendersky 
12890356975cSDavid Blaikie     if (!PrefixSet.insert(Prefix).second)
129013df4626SMatt Arsenault       return false;
129113df4626SMatt Arsenault 
129213df4626SMatt Arsenault     if (!ValidateCheckPrefix(Prefix))
129313df4626SMatt Arsenault       return false;
129413df4626SMatt Arsenault   }
129513df4626SMatt Arsenault 
129613df4626SMatt Arsenault   return true;
129713df4626SMatt Arsenault }
129813df4626SMatt Arsenault 
129913df4626SMatt Arsenault // I don't think there's a way to specify an initial value for cl::list,
130013df4626SMatt Arsenault // so if nothing was specified, add the default
130113df4626SMatt Arsenault static void AddCheckPrefixIfNeeded() {
130213df4626SMatt Arsenault   if (CheckPrefixes.empty())
130313df4626SMatt Arsenault     CheckPrefixes.push_back("CHECK");
1304c2735158SRui Ueyama }
1305c2735158SRui Ueyama 
13062bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) {
13072bd4f8b6SXinliang David Li   errs() << "FileCheck command line: ";
13082bd4f8b6SXinliang David Li   for (int I = 0; I < argc; I++)
13092bd4f8b6SXinliang David Li     errs() << " " << argv[I];
13102bd4f8b6SXinliang David Li   errs() << "\n";
13112bd4f8b6SXinliang David Li }
13122bd4f8b6SXinliang David Li 
1313ee3c74fbSChris Lattner int main(int argc, char **argv) {
13142ad6d48bSRichard Smith   sys::PrintStackTraceOnErrorSignal(argv[0]);
1315ee3c74fbSChris Lattner   PrettyStackTraceProgram X(argc, argv);
1316ee3c74fbSChris Lattner   cl::ParseCommandLineOptions(argc, argv);
1317ee3c74fbSChris Lattner 
131813df4626SMatt Arsenault   if (!ValidateCheckPrefixes()) {
131913df4626SMatt Arsenault     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
132013df4626SMatt Arsenault               "start with a letter and contain only alphanumeric characters, "
132113df4626SMatt Arsenault               "hyphens and underscores\n";
1322c2735158SRui Ueyama     return 2;
1323c2735158SRui Ueyama   }
1324c2735158SRui Ueyama 
132513df4626SMatt Arsenault   AddCheckPrefixIfNeeded();
132613df4626SMatt Arsenault 
1327ee3c74fbSChris Lattner   SourceMgr SM;
1328ee3c74fbSChris Lattner 
1329ee3c74fbSChris Lattner   // Read the expected strings from the check file.
133026cccfe1SChris Lattner   std::vector<CheckString> CheckStrings;
1331ee3c74fbSChris Lattner   if (ReadCheckFile(SM, CheckStrings))
1332ee3c74fbSChris Lattner     return 2;
1333ee3c74fbSChris Lattner 
1334ee3c74fbSChris Lattner   // Open the file to check and add it to SourceMgr.
1335adf21f2aSRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
1336adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(InputFilename);
1337adf21f2aSRafael Espindola   if (std::error_code EC = FileOrErr.getError()) {
1338adf21f2aSRafael Espindola     errs() << "Could not open input file '" << InputFilename
1339adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
13408e1c6477SEli Bendersky     return 2;
1341ee3c74fbSChris Lattner   }
13423f6481d0SRafael Espindola   std::unique_ptr<MemoryBuffer> &File = FileOrErr.get();
13432c3e5cdfSChris Lattner 
13441b9f936fSJustin Bogner   if (File->getBufferSize() == 0 && !AllowEmptyInput) {
1345b692bed7SChris Lattner     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
13462bd4f8b6SXinliang David Li     DumpCommandLine(argc, argv);
13478e1c6477SEli Bendersky     return 2;
1348b692bed7SChris Lattner   }
1349b692bed7SChris Lattner 
13502c3e5cdfSChris Lattner   // Remove duplicate spaces in the input file if requested.
13515ea04c38SGuy Benyei   // Remove DOS style line endings.
13521961f14cSDavid Blaikie   std::unique_ptr<MemoryBuffer> F =
1353ce5dd1acSRafael Espindola       CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace);
13542c3e5cdfSChris Lattner 
1355ee3c74fbSChris Lattner   // Check that we have all of the expected strings, in order, in the input
1356ee3c74fbSChris Lattner   // file.
1357caa5fc0cSChris Lattner   StringRef Buffer = F->getBuffer();
1358ee3c74fbSChris Lattner 
13591961f14cSDavid Blaikie   SM.AddNewSourceBuffer(std::move(F), SMLoc());
13601961f14cSDavid Blaikie 
13611961f14cSDavid Blaikie   /// VariableTable - This holds all the current filecheck variables.
13621961f14cSDavid Blaikie   StringMap<StringRef> VariableTable;
13631961f14cSDavid Blaikie 
1364f8bd2e5bSStephen Lin   bool hasError = false;
1365ee3c74fbSChris Lattner 
1366f8bd2e5bSStephen Lin   unsigned i = 0, j = 0, e = CheckStrings.size();
1367ee3c74fbSChris Lattner 
1368f8bd2e5bSStephen Lin   while (true) {
1369f8bd2e5bSStephen Lin     StringRef CheckRegion;
1370f8bd2e5bSStephen Lin     if (j == e) {
1371f8bd2e5bSStephen Lin       CheckRegion = Buffer;
1372f8bd2e5bSStephen Lin     } else {
1373f8bd2e5bSStephen Lin       const CheckString &CheckLabelStr = CheckStrings[j];
137485913ccaSJames Y Knight       if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
1375f8bd2e5bSStephen Lin         ++j;
1376f8bd2e5bSStephen Lin         continue;
1377da108b4eSChris Lattner       }
1378da108b4eSChris Lattner 
1379f8bd2e5bSStephen Lin       // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1380f8bd2e5bSStephen Lin       size_t MatchLabelLen = 0;
1381e93a3a08SStephen Lin       size_t MatchLabelPos = CheckLabelStr.Check(SM, Buffer, true,
1382f8bd2e5bSStephen Lin                                                  MatchLabelLen, VariableTable);
1383f8bd2e5bSStephen Lin       if (MatchLabelPos == StringRef::npos) {
1384f8bd2e5bSStephen Lin         hasError = true;
1385f8bd2e5bSStephen Lin         break;
1386f8bd2e5bSStephen Lin       }
1387f8bd2e5bSStephen Lin 
1388f8bd2e5bSStephen Lin       CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
1389f8bd2e5bSStephen Lin       Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
1390f8bd2e5bSStephen Lin       ++j;
1391f8bd2e5bSStephen Lin     }
1392f8bd2e5bSStephen Lin 
1393f8bd2e5bSStephen Lin     for ( ; i != j; ++i) {
1394f8bd2e5bSStephen Lin       const CheckString &CheckStr = CheckStrings[i];
1395f8bd2e5bSStephen Lin 
1396f8bd2e5bSStephen Lin       // Check each string within the scanned region, including a second check
1397f8bd2e5bSStephen Lin       // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1398f8bd2e5bSStephen Lin       size_t MatchLen = 0;
1399e93a3a08SStephen Lin       size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen,
1400f8bd2e5bSStephen Lin                                        VariableTable);
1401f8bd2e5bSStephen Lin 
1402f8bd2e5bSStephen Lin       if (MatchPos == StringRef::npos) {
1403f8bd2e5bSStephen Lin         hasError = true;
1404f8bd2e5bSStephen Lin         i = j;
1405f8bd2e5bSStephen Lin         break;
1406f8bd2e5bSStephen Lin       }
1407f8bd2e5bSStephen Lin 
1408f8bd2e5bSStephen Lin       CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
1409f8bd2e5bSStephen Lin     }
1410f8bd2e5bSStephen Lin 
1411f8bd2e5bSStephen Lin     if (j == e)
1412f8bd2e5bSStephen Lin       break;
1413f8bd2e5bSStephen Lin   }
1414f8bd2e5bSStephen Lin 
1415f8bd2e5bSStephen Lin   return hasError ? 1 : 0;
1416ee3c74fbSChris Lattner }
1417