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 //
13b5ecceffSJames Henderson // This program exits with an exit 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"
24197194b6SRui Ueyama #include "llvm/Support/InitLLVM.h"
25ee3c74fbSChris Lattner #include "llvm/Support/MemoryBuffer.h"
26f08d2db9SChris Lattner #include "llvm/Support/Regex.h"
27ee3c74fbSChris Lattner #include "llvm/Support/SourceMgr.h"
28ee3c74fbSChris Lattner #include "llvm/Support/raw_ostream.h"
298879e06dSChris Lattner #include <algorithm>
30981af002SWill Dietz #include <cctype>
31e8b8f1bcSEli Bendersky #include <map>
32e8b8f1bcSEli Bendersky #include <string>
33a6e9c3e4SRafael Espindola #include <system_error>
34e8b8f1bcSEli Bendersky #include <vector>
35ee3c74fbSChris Lattner using namespace llvm;
36ee3c74fbSChris Lattner 
37ee3c74fbSChris Lattner static cl::opt<std::string>
38ee3c74fbSChris Lattner     CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
39ee3c74fbSChris Lattner 
40ee3c74fbSChris Lattner static cl::opt<std::string>
41ee3c74fbSChris Lattner     InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
42ee3c74fbSChris Lattner                   cl::init("-"), cl::value_desc("filename"));
43ee3c74fbSChris Lattner 
44e8f2fb20SChandler Carruth static cl::list<std::string> CheckPrefixes(
45e8f2fb20SChandler Carruth     "check-prefix",
46ee3c74fbSChris Lattner     cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
47fd557cb0SDaniel Sanders static cl::alias CheckPrefixesAlias(
48fd557cb0SDaniel Sanders     "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
49fd557cb0SDaniel Sanders     cl::NotHidden,
50fd557cb0SDaniel Sanders     cl::desc(
51fd557cb0SDaniel Sanders         "Alias for -check-prefix permitting multiple comma separated values"));
52ee3c74fbSChris Lattner 
53e8f2fb20SChandler Carruth static cl::opt<bool> NoCanonicalizeWhiteSpace(
54e8f2fb20SChandler Carruth     "strict-whitespace",
552c3e5cdfSChris Lattner     cl::desc("Do not treat all horizontal whitespace as equivalent"));
562c3e5cdfSChris Lattner 
5756ccdbbdSAlexander Kornienko static cl::list<std::string> ImplicitCheckNot(
5856ccdbbdSAlexander Kornienko     "implicit-check-not",
5956ccdbbdSAlexander Kornienko     cl::desc("Add an implicit negative check with this pattern to every\n"
6056ccdbbdSAlexander Kornienko              "positive check. This can be used to ensure that no instances of\n"
6156ccdbbdSAlexander Kornienko              "this pattern occur which are not matched by a positive pattern"),
6256ccdbbdSAlexander Kornienko     cl::value_desc("pattern"));
6356ccdbbdSAlexander Kornienko 
6446e1fd61SAlexander Richardson static cl::list<std::string> GlobalDefines("D", cl::Prefix,
6546e1fd61SAlexander Richardson     cl::desc("Define a variable to be used in capture patterns."),
6646e1fd61SAlexander Richardson     cl::value_desc("VAR=VALUE"));
6746e1fd61SAlexander Richardson 
681b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput(
691b9f936fSJustin Bogner     "allow-empty", cl::init(false),
701b9f936fSJustin Bogner     cl::desc("Allow the input file to be empty. This is useful when making\n"
711b9f936fSJustin Bogner              "checks that some error message does not occur, for example."));
721b9f936fSJustin Bogner 
7385913ccaSJames Y Knight static cl::opt<bool> MatchFullLines(
7485913ccaSJames Y Knight     "match-full-lines", cl::init(false),
7585913ccaSJames Y Knight     cl::desc("Require all positive matches to cover an entire input line.\n"
7685913ccaSJames Y Knight              "Allows leading and trailing whitespace if --strict-whitespace\n"
7785913ccaSJames Y Knight              "is not also passed."));
7885913ccaSJames Y Knight 
79f55e72a5SArtem Belevich static cl::opt<bool> EnableVarScope(
80f55e72a5SArtem Belevich     "enable-var-scope", cl::init(false),
81f55e72a5SArtem Belevich     cl::desc("Enables scope for regex variables. Variables with names that\n"
82f55e72a5SArtem Belevich              "do not start with '$' will be reset at the beginning of\n"
83f55e72a5SArtem Belevich              "each CHECK-LABEL block."));
84f55e72a5SArtem Belevich 
8513df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator;
8613df4626SMatt Arsenault 
8774d50731SChris Lattner //===----------------------------------------------------------------------===//
8874d50731SChris Lattner // Pattern Handling Code.
8974d50731SChris Lattner //===----------------------------------------------------------------------===//
9074d50731SChris Lattner 
9138820972SMatt Arsenault namespace Check {
9238820972SMatt Arsenault enum CheckType {
9338820972SMatt Arsenault   CheckNone = 0,
9438820972SMatt Arsenault   CheckPlain,
9538820972SMatt Arsenault   CheckNext,
9601ac1707SDuncan P. N. Exon Smith   CheckSame,
9738820972SMatt Arsenault   CheckNot,
9838820972SMatt Arsenault   CheckDAG,
9938820972SMatt Arsenault   CheckLabel,
100*5507f668SJames Henderson   CheckEmpty,
1010a4c44bdSChris Lattner 
1024dabac20SChandler Carruth   /// Indicates the pattern only matches the end of file. This is used for
1034dabac20SChandler Carruth   /// trailing CHECK-NOTs.
104a908e7bdSPaul Robinson   CheckEOF,
1054dabac20SChandler Carruth 
1064dabac20SChandler Carruth   /// Marks when parsing found a -NOT check combined with another CHECK suffix.
107a908e7bdSPaul Robinson   CheckBadNot
10838820972SMatt Arsenault };
10938820972SMatt Arsenault }
110eba55822SJakob Stoklund Olesen 
11138820972SMatt Arsenault class Pattern {
11238820972SMatt Arsenault   SMLoc PatternLoc;
11391a1b2c9SMichael Liao 
1144dabac20SChandler Carruth   /// A fixed string to match as the pattern or empty if this pattern requires
1154dabac20SChandler Carruth   /// a regex match.
116221460e0SChris Lattner   StringRef FixedStr;
117b16ab0c4SChris Lattner 
1184dabac20SChandler Carruth   /// A regex string to match as the pattern or empty if this pattern requires
1194dabac20SChandler Carruth   /// a fixed string to match.
120b16ab0c4SChris Lattner   std::string RegExStr;
1218879e06dSChris Lattner 
1224dabac20SChandler Carruth   /// Entries in this vector map to uses of a variable in the pattern, e.g.
1234dabac20SChandler Carruth   /// "foo[[bar]]baz".  In this case, the RegExStr will contain "foobaz" and
1244dabac20SChandler Carruth   /// we'll get an entry in this vector that tells us to insert the value of
1254dabac20SChandler Carruth   /// bar at offset 3.
1268879e06dSChris Lattner   std::vector<std::pair<StringRef, unsigned>> VariableUses;
1278879e06dSChris Lattner 
1284dabac20SChandler Carruth   /// Maps definitions of variables to their parenthesized capture numbers.
1294dabac20SChandler Carruth   ///
1304dabac20SChandler Carruth   /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to
1314dabac20SChandler Carruth   /// 1.
132e8b8f1bcSEli Bendersky   std::map<StringRef, unsigned> VariableDefs;
1338879e06dSChris Lattner 
134d1e020f7SSaleem Abdulrasool   Check::CheckType CheckTy;
1353b40b445SChris Lattner 
1364dabac20SChandler Carruth   /// Contains the number of line this pattern is in.
137d1e020f7SSaleem Abdulrasool   unsigned LineNumber;
138d1e020f7SSaleem Abdulrasool 
139d1e020f7SSaleem Abdulrasool public:
140d1e020f7SSaleem Abdulrasool   explicit Pattern(Check::CheckType Ty) : CheckTy(Ty) {}
14174d50731SChris Lattner 
1424dabac20SChandler Carruth   /// Returns the location in source code.
1430b707eb8SMichael Liao   SMLoc getLoc() const { return PatternLoc; }
1440b707eb8SMichael Liao 
145e8f2fb20SChandler Carruth   bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
14613df4626SMatt Arsenault                     unsigned LineNumber);
1478879e06dSChris Lattner   size_t Match(StringRef Buffer, size_t &MatchLen,
1488879e06dSChris Lattner                StringMap<StringRef> &VariableTable) const;
149e0ef65abSDaniel Dunbar   void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
150e0ef65abSDaniel Dunbar                         const StringMap<StringRef> &VariableTable) const;
151e0ef65abSDaniel Dunbar 
152e8f2fb20SChandler Carruth   bool hasVariable() const {
153e8f2fb20SChandler Carruth     return !(VariableUses.empty() && VariableDefs.empty());
154e8f2fb20SChandler Carruth   }
155f8bd2e5bSStephen Lin 
15638820972SMatt Arsenault   Check::CheckType getCheckTy() const { return CheckTy; }
15791a1b2c9SMichael Liao 
158b16ab0c4SChris Lattner private:
159e8b8f1bcSEli Bendersky   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
160e8b8f1bcSEli Bendersky   void AddBackrefToRegEx(unsigned BackrefNum);
161e8f2fb20SChandler Carruth   unsigned
162e8f2fb20SChandler Carruth   ComputeMatchDistance(StringRef Buffer,
163fd29d886SDaniel Dunbar                        const StringMap<StringRef> &VariableTable) const;
16492987fb3SAlexander Kornienko   bool EvaluateExpression(StringRef Expr, std::string &Value) const;
16581e5cd9eSAdrian Prantl   size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
1663b40b445SChris Lattner };
1673b40b445SChris Lattner 
1684dabac20SChandler Carruth /// Parses the given string into the Pattern.
1694dabac20SChandler Carruth ///
1704dabac20SChandler Carruth /// \p Prefix provides which prefix is being matched, \p SM provides the
1714dabac20SChandler Carruth /// SourceMgr used for error reports, and \p LineNumber is the line number in
1724dabac20SChandler Carruth /// the input file from which the pattern string was read. Returns true in
1734dabac20SChandler Carruth /// case of an error, false otherwise.
174e8f2fb20SChandler Carruth bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
175e8f2fb20SChandler Carruth                            SourceMgr &SM, unsigned LineNumber) {
17685913ccaSJames Y Knight   bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot;
17785913ccaSJames Y Knight 
17892987fb3SAlexander Kornienko   this->LineNumber = LineNumber;
1790a4c44bdSChris Lattner   PatternLoc = SMLoc::getFromPointer(PatternStr.data());
1800a4c44bdSChris Lattner 
1811714676aSTom de Vries   if (!(NoCanonicalizeWhiteSpace && MatchFullLines))
18274d50731SChris Lattner     // Ignore trailing whitespace.
18374d50731SChris Lattner     while (!PatternStr.empty() &&
18474d50731SChris Lattner            (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
18574d50731SChris Lattner       PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
18674d50731SChris Lattner 
18774d50731SChris Lattner   // Check that there is something on the line.
188*5507f668SJames Henderson   if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
18903b80a40SChris Lattner     SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
190e8f2fb20SChandler Carruth                     "found empty check string with prefix '" + Prefix + ":'");
19174d50731SChris Lattner     return true;
19274d50731SChris Lattner   }
19374d50731SChris Lattner 
194*5507f668SJames Henderson   if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
195*5507f668SJames Henderson     SM.PrintMessage(
196*5507f668SJames Henderson         PatternLoc, SourceMgr::DK_Error,
197*5507f668SJames Henderson         "found non-empty check string for empty check with prefix '" + Prefix +
198*5507f668SJames Henderson             ":'");
199*5507f668SJames Henderson     return true;
200*5507f668SJames Henderson   }
201*5507f668SJames Henderson 
202*5507f668SJames Henderson   if (CheckTy == Check::CheckEmpty) {
203*5507f668SJames Henderson     RegExStr = "(\n$)";
204*5507f668SJames Henderson     return false;
205*5507f668SJames Henderson   }
206*5507f668SJames Henderson 
207221460e0SChris Lattner   // Check to see if this is a fixed string, or if it has regex pieces.
20885913ccaSJames Y Knight   if (!MatchFullLinesHere &&
20985913ccaSJames Y Knight       (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
21085913ccaSJames Y Knight                                  PatternStr.find("[[") == StringRef::npos))) {
211221460e0SChris Lattner     FixedStr = PatternStr;
212221460e0SChris Lattner     return false;
213221460e0SChris Lattner   }
214221460e0SChris Lattner 
21585913ccaSJames Y Knight   if (MatchFullLinesHere) {
21685913ccaSJames Y Knight     RegExStr += '^';
21785913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
21885913ccaSJames Y Knight       RegExStr += " *";
21985913ccaSJames Y Knight   }
22085913ccaSJames Y Knight 
2218879e06dSChris Lattner   // Paren value #0 is for the fully matched string.  Any new parenthesized
22253e0679dSChris Lattner   // values add from there.
2238879e06dSChris Lattner   unsigned CurParen = 1;
2248879e06dSChris Lattner 
225b16ab0c4SChris Lattner   // Otherwise, there is at least one regex piece.  Build up the regex pattern
226b16ab0c4SChris Lattner   // by escaping scary characters in fixed strings, building up one big regex.
227f08d2db9SChris Lattner   while (!PatternStr.empty()) {
2288879e06dSChris Lattner     // RegEx matches.
22953e0679dSChris Lattner     if (PatternStr.startswith("{{")) {
23043d50d4aSEli Bendersky       // This is the start of a regex match.  Scan for the }}.
231f08d2db9SChris Lattner       size_t End = PatternStr.find("}}");
232f08d2db9SChris Lattner       if (End == StringRef::npos) {
233f08d2db9SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
23403b80a40SChris Lattner                         SourceMgr::DK_Error,
23503b80a40SChris Lattner                         "found start of regex string with no end '}}'");
236f08d2db9SChris Lattner         return true;
237f08d2db9SChris Lattner       }
238f08d2db9SChris Lattner 
239e53c95f1SChris Lattner       // Enclose {{}} patterns in parens just like [[]] even though we're not
240e53c95f1SChris Lattner       // capturing the result for any purpose.  This is required in case the
241e53c95f1SChris Lattner       // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
242e53c95f1SChris Lattner       // want this to turn into: "abc(x|z)def" not "abcx|zdef".
243e53c95f1SChris Lattner       RegExStr += '(';
244e53c95f1SChris Lattner       ++CurParen;
245e53c95f1SChris Lattner 
2468879e06dSChris Lattner       if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
2478879e06dSChris Lattner         return true;
248e53c95f1SChris Lattner       RegExStr += ')';
24953e0679dSChris Lattner 
2508879e06dSChris Lattner       PatternStr = PatternStr.substr(End + 2);
2518879e06dSChris Lattner       continue;
2528879e06dSChris Lattner     }
2538879e06dSChris Lattner 
2548879e06dSChris Lattner     // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
2558879e06dSChris Lattner     // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
2568879e06dSChris Lattner     // second form is [[foo]] which is a reference to foo.  The variable name
25757cb733bSDaniel Dunbar     // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
2588879e06dSChris Lattner     // it.  This is to catch some common errors.
25953e0679dSChris Lattner     if (PatternStr.startswith("[[")) {
260061d2baaSEli Bendersky       // Find the closing bracket pair ending the match.  End is going to be an
261061d2baaSEli Bendersky       // offset relative to the beginning of the match string.
26281e5cd9eSAdrian Prantl       size_t End = FindRegexVarEnd(PatternStr.substr(2), SM);
263061d2baaSEli Bendersky 
2648879e06dSChris Lattner       if (End == StringRef::npos) {
2658879e06dSChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
26603b80a40SChris Lattner                         SourceMgr::DK_Error,
26703b80a40SChris Lattner                         "invalid named regex reference, no ]] found");
268f08d2db9SChris Lattner         return true;
269f08d2db9SChris Lattner       }
270f08d2db9SChris Lattner 
271061d2baaSEli Bendersky       StringRef MatchStr = PatternStr.substr(2, End);
272061d2baaSEli Bendersky       PatternStr = PatternStr.substr(End + 4);
2738879e06dSChris Lattner 
2748879e06dSChris Lattner       // Get the regex name (e.g. "foo").
2758879e06dSChris Lattner       size_t NameEnd = MatchStr.find(':');
2768879e06dSChris Lattner       StringRef Name = MatchStr.substr(0, NameEnd);
2778879e06dSChris Lattner 
2788879e06dSChris Lattner       if (Name.empty()) {
27903b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
28003b80a40SChris Lattner                         "invalid name in named regex: empty name");
2818879e06dSChris Lattner         return true;
2828879e06dSChris Lattner       }
2838879e06dSChris Lattner 
28492987fb3SAlexander Kornienko       // Verify that the name/expression is well formed. FileCheck currently
28592987fb3SAlexander Kornienko       // supports @LINE, @LINE+number, @LINE-number expressions. The check here
28692987fb3SAlexander Kornienko       // is relaxed, more strict check is performed in \c EvaluateExpression.
28792987fb3SAlexander Kornienko       bool IsExpression = false;
28892987fb3SAlexander Kornienko       for (unsigned i = 0, e = Name.size(); i != e; ++i) {
289f55e72a5SArtem Belevich         if (i == 0) {
290f55e72a5SArtem Belevich           if (Name[i] == '$')  // Global vars start with '$'
291f55e72a5SArtem Belevich             continue;
292f55e72a5SArtem Belevich           if (Name[i] == '@') {
29392987fb3SAlexander Kornienko             if (NameEnd != StringRef::npos) {
29492987fb3SAlexander Kornienko               SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
29592987fb3SAlexander Kornienko                               SourceMgr::DK_Error,
29692987fb3SAlexander Kornienko                               "invalid name in named regex definition");
29792987fb3SAlexander Kornienko               return true;
29892987fb3SAlexander Kornienko             }
29992987fb3SAlexander Kornienko             IsExpression = true;
30092987fb3SAlexander Kornienko             continue;
30192987fb3SAlexander Kornienko           }
302f55e72a5SArtem Belevich         }
30392987fb3SAlexander Kornienko         if (Name[i] != '_' && !isalnum(Name[i]) &&
30492987fb3SAlexander Kornienko             (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
3058879e06dSChris Lattner           SM.PrintMessage(SMLoc::getFromPointer(Name.data() + i),
30603b80a40SChris Lattner                           SourceMgr::DK_Error, "invalid name in named regex");
3078879e06dSChris Lattner           return true;
3088879e06dSChris Lattner         }
30992987fb3SAlexander Kornienko       }
3108879e06dSChris Lattner 
3118879e06dSChris Lattner       // Name can't start with a digit.
31283c74e9fSGuy Benyei       if (isdigit(static_cast<unsigned char>(Name[0]))) {
31303b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
31403b80a40SChris Lattner                         "invalid name in named regex");
3158879e06dSChris Lattner         return true;
3168879e06dSChris Lattner       }
3178879e06dSChris Lattner 
3188879e06dSChris Lattner       // Handle [[foo]].
3198879e06dSChris Lattner       if (NameEnd == StringRef::npos) {
320e8b8f1bcSEli Bendersky         // Handle variables that were defined earlier on the same line by
321e8b8f1bcSEli Bendersky         // emitting a backreference.
322e8b8f1bcSEli Bendersky         if (VariableDefs.find(Name) != VariableDefs.end()) {
323e8b8f1bcSEli Bendersky           unsigned VarParenNum = VariableDefs[Name];
324e8b8f1bcSEli Bendersky           if (VarParenNum < 1 || VarParenNum > 9) {
325e8b8f1bcSEli Bendersky             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
326e8b8f1bcSEli Bendersky                             SourceMgr::DK_Error,
327e8b8f1bcSEli Bendersky                             "Can't back-reference more than 9 variables");
328e8b8f1bcSEli Bendersky             return true;
329e8b8f1bcSEli Bendersky           }
330e8b8f1bcSEli Bendersky           AddBackrefToRegEx(VarParenNum);
331e8b8f1bcSEli Bendersky         } else {
3328879e06dSChris Lattner           VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
333e8b8f1bcSEli Bendersky         }
3348879e06dSChris Lattner         continue;
3358879e06dSChris Lattner       }
3368879e06dSChris Lattner 
3378879e06dSChris Lattner       // Handle [[foo:.*]].
338e8b8f1bcSEli Bendersky       VariableDefs[Name] = CurParen;
3398879e06dSChris Lattner       RegExStr += '(';
3408879e06dSChris Lattner       ++CurParen;
3418879e06dSChris Lattner 
3428879e06dSChris Lattner       if (AddRegExToRegEx(MatchStr.substr(NameEnd + 1), CurParen, SM))
3438879e06dSChris Lattner         return true;
3448879e06dSChris Lattner 
3458879e06dSChris Lattner       RegExStr += ')';
3468879e06dSChris Lattner     }
3478879e06dSChris Lattner 
3488879e06dSChris Lattner     // Handle fixed string matches.
3498879e06dSChris Lattner     // Find the end, which is the start of the next regex.
3508879e06dSChris Lattner     size_t FixedMatchEnd = PatternStr.find("{{");
3518879e06dSChris Lattner     FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
3526f4f77b7SHans Wennborg     RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
3538879e06dSChris Lattner     PatternStr = PatternStr.substr(FixedMatchEnd);
354f08d2db9SChris Lattner   }
355f08d2db9SChris Lattner 
35685913ccaSJames Y Knight   if (MatchFullLinesHere) {
35785913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
35885913ccaSJames Y Knight       RegExStr += " *";
35985913ccaSJames Y Knight     RegExStr += '$';
36085913ccaSJames Y Knight   }
36185913ccaSJames Y Knight 
36274d50731SChris Lattner   return false;
36374d50731SChris Lattner }
36474d50731SChris Lattner 
365e8f2fb20SChandler Carruth bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
366e8b8f1bcSEli Bendersky   Regex R(RS);
3678879e06dSChris Lattner   std::string Error;
3688879e06dSChris Lattner   if (!R.isValid(Error)) {
369e8b8f1bcSEli Bendersky     SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
37003b80a40SChris Lattner                     "invalid regex: " + Error);
3718879e06dSChris Lattner     return true;
3728879e06dSChris Lattner   }
3738879e06dSChris Lattner 
374e8b8f1bcSEli Bendersky   RegExStr += RS.str();
3758879e06dSChris Lattner   CurParen += R.getNumMatches();
3768879e06dSChris Lattner   return false;
3778879e06dSChris Lattner }
378b16ab0c4SChris Lattner 
379e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
380e8b8f1bcSEli Bendersky   assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
381e8f2fb20SChandler Carruth   std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
382e8b8f1bcSEli Bendersky   RegExStr += Backref;
383e8b8f1bcSEli Bendersky }
384e8b8f1bcSEli Bendersky 
3854dabac20SChandler Carruth /// Evaluates expression and stores the result to \p Value.
3864dabac20SChandler Carruth ///
3874dabac20SChandler Carruth /// Returns true on success and false when the expression has invalid syntax.
38892987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
38992987fb3SAlexander Kornienko   // The only supported expression is @LINE([\+-]\d+)?
39092987fb3SAlexander Kornienko   if (!Expr.startswith("@LINE"))
39192987fb3SAlexander Kornienko     return false;
39292987fb3SAlexander Kornienko   Expr = Expr.substr(StringRef("@LINE").size());
39392987fb3SAlexander Kornienko   int Offset = 0;
39492987fb3SAlexander Kornienko   if (!Expr.empty()) {
39592987fb3SAlexander Kornienko     if (Expr[0] == '+')
39692987fb3SAlexander Kornienko       Expr = Expr.substr(1);
39792987fb3SAlexander Kornienko     else if (Expr[0] != '-')
39892987fb3SAlexander Kornienko       return false;
39992987fb3SAlexander Kornienko     if (Expr.getAsInteger(10, Offset))
40092987fb3SAlexander Kornienko       return false;
40192987fb3SAlexander Kornienko   }
40292987fb3SAlexander Kornienko   Value = llvm::itostr(LineNumber + Offset);
40392987fb3SAlexander Kornienko   return true;
40492987fb3SAlexander Kornienko }
40592987fb3SAlexander Kornienko 
4064dabac20SChandler Carruth /// Matches the pattern string against the input buffer \p Buffer
4074dabac20SChandler Carruth ///
4084dabac20SChandler Carruth /// This returns the position that is matched or npos if there is no match. If
4094dabac20SChandler Carruth /// there is a match, the size of the matched string is returned in \p
4104dabac20SChandler Carruth /// MatchLen.
4114dabac20SChandler Carruth ///
4124dabac20SChandler Carruth /// The \p VariableTable StringMap provides the current values of filecheck
4134dabac20SChandler Carruth /// variables and is updated if this match defines new values.
4148879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
4158879e06dSChris Lattner                       StringMap<StringRef> &VariableTable) const {
416eba55822SJakob Stoklund Olesen   // If this is the EOF pattern, match it immediately.
41738820972SMatt Arsenault   if (CheckTy == Check::CheckEOF) {
418eba55822SJakob Stoklund Olesen     MatchLen = 0;
419eba55822SJakob Stoklund Olesen     return Buffer.size();
420eba55822SJakob Stoklund Olesen   }
421eba55822SJakob Stoklund Olesen 
422221460e0SChris Lattner   // If this is a fixed string pattern, just match it now.
423221460e0SChris Lattner   if (!FixedStr.empty()) {
424221460e0SChris Lattner     MatchLen = FixedStr.size();
425221460e0SChris Lattner     return Buffer.find(FixedStr);
426221460e0SChris Lattner   }
427221460e0SChris Lattner 
428b16ab0c4SChris Lattner   // Regex match.
4298879e06dSChris Lattner 
4308879e06dSChris Lattner   // If there are variable uses, we need to create a temporary string with the
4318879e06dSChris Lattner   // actual value.
4328879e06dSChris Lattner   StringRef RegExToMatch = RegExStr;
4338879e06dSChris Lattner   std::string TmpStr;
4348879e06dSChris Lattner   if (!VariableUses.empty()) {
4358879e06dSChris Lattner     TmpStr = RegExStr;
4368879e06dSChris Lattner 
4378879e06dSChris Lattner     unsigned InsertOffset = 0;
4388f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
43992987fb3SAlexander Kornienko       std::string Value;
44092987fb3SAlexander Kornienko 
4418f870499SBenjamin Kramer       if (VariableUse.first[0] == '@') {
4428f870499SBenjamin Kramer         if (!EvaluateExpression(VariableUse.first, Value))
44392987fb3SAlexander Kornienko           return StringRef::npos;
44492987fb3SAlexander Kornienko       } else {
445e0ef65abSDaniel Dunbar         StringMap<StringRef>::iterator it =
4468f870499SBenjamin Kramer             VariableTable.find(VariableUse.first);
447e0ef65abSDaniel Dunbar         // If the variable is undefined, return an error.
448e0ef65abSDaniel Dunbar         if (it == VariableTable.end())
449e0ef65abSDaniel Dunbar           return StringRef::npos;
450e0ef65abSDaniel Dunbar 
4516f4f77b7SHans Wennborg         // Look up the value and escape it so that we can put it into the regex.
4526f4f77b7SHans Wennborg         Value += Regex::escape(it->second);
45392987fb3SAlexander Kornienko       }
4548879e06dSChris Lattner 
4558879e06dSChris Lattner       // Plop it into the regex at the adjusted offset.
4568f870499SBenjamin Kramer       TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset,
4578879e06dSChris Lattner                     Value.begin(), Value.end());
4588879e06dSChris Lattner       InsertOffset += Value.size();
4598879e06dSChris Lattner     }
4608879e06dSChris Lattner 
4618879e06dSChris Lattner     // Match the newly constructed regex.
4628879e06dSChris Lattner     RegExToMatch = TmpStr;
4638879e06dSChris Lattner   }
4648879e06dSChris Lattner 
465b16ab0c4SChris Lattner   SmallVector<StringRef, 4> MatchInfo;
4668879e06dSChris Lattner   if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
467f08d2db9SChris Lattner     return StringRef::npos;
468b16ab0c4SChris Lattner 
469b16ab0c4SChris Lattner   // Successful regex match.
470b16ab0c4SChris Lattner   assert(!MatchInfo.empty() && "Didn't get any match");
471b16ab0c4SChris Lattner   StringRef FullMatch = MatchInfo[0];
472b16ab0c4SChris Lattner 
4738879e06dSChris Lattner   // If this defines any variables, remember their values.
4748f870499SBenjamin Kramer   for (const auto &VariableDef : VariableDefs) {
4758f870499SBenjamin Kramer     assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
4768f870499SBenjamin Kramer     VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
4770a4c44bdSChris Lattner   }
4780a4c44bdSChris Lattner 
479b16ab0c4SChris Lattner   MatchLen = FullMatch.size();
480b16ab0c4SChris Lattner   return FullMatch.data() - Buffer.data();
481f08d2db9SChris Lattner }
482f08d2db9SChris Lattner 
4834dabac20SChandler Carruth 
4844dabac20SChandler Carruth /// Computes an arbitrary estimate for the quality of matching this pattern at
4854dabac20SChandler Carruth /// the start of \p Buffer; a distance of zero should correspond to a perfect
4864dabac20SChandler Carruth /// match.
487e8f2fb20SChandler Carruth unsigned
488e8f2fb20SChandler Carruth Pattern::ComputeMatchDistance(StringRef Buffer,
489fd29d886SDaniel Dunbar                               const StringMap<StringRef> &VariableTable) const {
490fd29d886SDaniel Dunbar   // Just compute the number of matching characters. For regular expressions, we
491fd29d886SDaniel Dunbar   // just compare against the regex itself and hope for the best.
492fd29d886SDaniel Dunbar   //
493fd29d886SDaniel Dunbar   // FIXME: One easy improvement here is have the regex lib generate a single
494fd29d886SDaniel Dunbar   // example regular expression which matches, and use that as the example
495fd29d886SDaniel Dunbar   // string.
496fd29d886SDaniel Dunbar   StringRef ExampleString(FixedStr);
497fd29d886SDaniel Dunbar   if (ExampleString.empty())
498fd29d886SDaniel Dunbar     ExampleString = RegExStr;
499fd29d886SDaniel Dunbar 
500e9aa36c8SDaniel Dunbar   // Only compare up to the first line in the buffer, or the string size.
501e9aa36c8SDaniel Dunbar   StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
502e9aa36c8SDaniel Dunbar   BufferPrefix = BufferPrefix.split('\n').first;
503e9aa36c8SDaniel Dunbar   return BufferPrefix.edit_distance(ExampleString);
504fd29d886SDaniel Dunbar }
505fd29d886SDaniel Dunbar 
5064dabac20SChandler Carruth /// Prints additional information about a failure to match involving this
5074dabac20SChandler Carruth /// pattern.
508e8f2fb20SChandler Carruth void Pattern::PrintFailureInfo(
509e8f2fb20SChandler Carruth     const SourceMgr &SM, StringRef Buffer,
510e0ef65abSDaniel Dunbar     const StringMap<StringRef> &VariableTable) const {
511e0ef65abSDaniel Dunbar   // If this was a regular expression using variables, print the current
512e0ef65abSDaniel Dunbar   // variable values.
513e0ef65abSDaniel Dunbar   if (!VariableUses.empty()) {
5148f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
515e69170a1SAlp Toker       SmallString<256> Msg;
516e69170a1SAlp Toker       raw_svector_ostream OS(Msg);
5178f870499SBenjamin Kramer       StringRef Var = VariableUse.first;
51892987fb3SAlexander Kornienko       if (Var[0] == '@') {
51992987fb3SAlexander Kornienko         std::string Value;
52092987fb3SAlexander Kornienko         if (EvaluateExpression(Var, Value)) {
52192987fb3SAlexander Kornienko           OS << "with expression \"";
52292987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\" equal to \"";
52392987fb3SAlexander Kornienko           OS.write_escaped(Value) << "\"";
52492987fb3SAlexander Kornienko         } else {
52592987fb3SAlexander Kornienko           OS << "uses incorrect expression \"";
52692987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
52792987fb3SAlexander Kornienko         }
52892987fb3SAlexander Kornienko       } else {
52992987fb3SAlexander Kornienko         StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
530e0ef65abSDaniel Dunbar 
531e0ef65abSDaniel Dunbar         // Check for undefined variable references.
532e0ef65abSDaniel Dunbar         if (it == VariableTable.end()) {
533e0ef65abSDaniel Dunbar           OS << "uses undefined variable \"";
53492987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
535e0ef65abSDaniel Dunbar         } else {
536e0ef65abSDaniel Dunbar           OS << "with variable \"";
537e0ef65abSDaniel Dunbar           OS.write_escaped(Var) << "\" equal to \"";
538e0ef65abSDaniel Dunbar           OS.write_escaped(it->second) << "\"";
539e0ef65abSDaniel Dunbar         }
54092987fb3SAlexander Kornienko       }
541e0ef65abSDaniel Dunbar 
54203b80a40SChris Lattner       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
54303b80a40SChris Lattner                       OS.str());
544e0ef65abSDaniel Dunbar     }
545e0ef65abSDaniel Dunbar   }
546fd29d886SDaniel Dunbar 
547fd29d886SDaniel Dunbar   // Attempt to find the closest/best fuzzy match.  Usually an error happens
548fd29d886SDaniel Dunbar   // because some string in the output didn't exactly match. In these cases, we
549fd29d886SDaniel Dunbar   // would like to show the user a best guess at what "should have" matched, to
550fd29d886SDaniel Dunbar   // save them having to actually check the input manually.
551fd29d886SDaniel Dunbar   size_t NumLinesForward = 0;
552fd29d886SDaniel Dunbar   size_t Best = StringRef::npos;
553fd29d886SDaniel Dunbar   double BestQuality = 0;
554fd29d886SDaniel Dunbar 
555fd29d886SDaniel Dunbar   // Use an arbitrary 4k limit on how far we will search.
5562bf486ebSDan Gohman   for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
557fd29d886SDaniel Dunbar     if (Buffer[i] == '\n')
558fd29d886SDaniel Dunbar       ++NumLinesForward;
559fd29d886SDaniel Dunbar 
560df22bbf7SDan Gohman     // Patterns have leading whitespace stripped, so skip whitespace when
561df22bbf7SDan Gohman     // looking for something which looks like a pattern.
562df22bbf7SDan Gohman     if (Buffer[i] == ' ' || Buffer[i] == '\t')
563df22bbf7SDan Gohman       continue;
564df22bbf7SDan Gohman 
565fd29d886SDaniel Dunbar     // Compute the "quality" of this match as an arbitrary combination of the
566fd29d886SDaniel Dunbar     // match distance and the number of lines skipped to get to this match.
567fd29d886SDaniel Dunbar     unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
568fd29d886SDaniel Dunbar     double Quality = Distance + (NumLinesForward / 100.);
569fd29d886SDaniel Dunbar 
570fd29d886SDaniel Dunbar     if (Quality < BestQuality || Best == StringRef::npos) {
571fd29d886SDaniel Dunbar       Best = i;
572fd29d886SDaniel Dunbar       BestQuality = Quality;
573fd29d886SDaniel Dunbar     }
574fd29d886SDaniel Dunbar   }
575fd29d886SDaniel Dunbar 
576fd29d886SDaniel Dunbar   // Print the "possible intended match here" line if we found something
577c069cc8eSDaniel Dunbar   // reasonable and not equal to what we showed in the "scanning from here"
578c069cc8eSDaniel Dunbar   // line.
579c069cc8eSDaniel Dunbar   if (Best && Best != StringRef::npos && BestQuality < 50) {
580fd29d886SDaniel Dunbar     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
58103b80a40SChris Lattner                     SourceMgr::DK_Note, "possible intended match here");
582fd29d886SDaniel Dunbar 
583fd29d886SDaniel Dunbar     // FIXME: If we wanted to be really friendly we would show why the match
584fd29d886SDaniel Dunbar     // failed, as it can be hard to spot simple one character differences.
585fd29d886SDaniel Dunbar   }
586e0ef65abSDaniel Dunbar }
58774d50731SChris Lattner 
5884dabac20SChandler Carruth /// Finds the closing sequence of a regex variable usage or definition.
5894dabac20SChandler Carruth ///
5904dabac20SChandler Carruth /// \p Str has to point in the beginning of the definition (right after the
5914dabac20SChandler Carruth /// opening sequence). Returns the offset of the closing sequence within Str,
5924dabac20SChandler Carruth /// or npos if it was not found.
59381e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
594061d2baaSEli Bendersky   // Offset keeps track of the current offset within the input Str
595061d2baaSEli Bendersky   size_t Offset = 0;
596061d2baaSEli Bendersky   // [...] Nesting depth
597061d2baaSEli Bendersky   size_t BracketDepth = 0;
598061d2baaSEli Bendersky 
599061d2baaSEli Bendersky   while (!Str.empty()) {
600061d2baaSEli Bendersky     if (Str.startswith("]]") && BracketDepth == 0)
601061d2baaSEli Bendersky       return Offset;
602061d2baaSEli Bendersky     if (Str[0] == '\\') {
603061d2baaSEli Bendersky       // Backslash escapes the next char within regexes, so skip them both.
604061d2baaSEli Bendersky       Str = Str.substr(2);
605061d2baaSEli Bendersky       Offset += 2;
606061d2baaSEli Bendersky     } else {
607061d2baaSEli Bendersky       switch (Str[0]) {
608061d2baaSEli Bendersky       default:
609061d2baaSEli Bendersky         break;
610061d2baaSEli Bendersky       case '[':
611061d2baaSEli Bendersky         BracketDepth++;
612061d2baaSEli Bendersky         break;
613061d2baaSEli Bendersky       case ']':
61481e5cd9eSAdrian Prantl         if (BracketDepth == 0) {
61581e5cd9eSAdrian Prantl           SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
61681e5cd9eSAdrian Prantl                           SourceMgr::DK_Error,
61781e5cd9eSAdrian Prantl                           "missing closing \"]\" for regex variable");
61881e5cd9eSAdrian Prantl           exit(1);
61981e5cd9eSAdrian Prantl         }
620061d2baaSEli Bendersky         BracketDepth--;
621061d2baaSEli Bendersky         break;
622061d2baaSEli Bendersky       }
623061d2baaSEli Bendersky       Str = Str.substr(1);
624061d2baaSEli Bendersky       Offset++;
625061d2baaSEli Bendersky     }
626061d2baaSEli Bendersky   }
627061d2baaSEli Bendersky 
628061d2baaSEli Bendersky   return StringRef::npos;
629061d2baaSEli Bendersky }
630061d2baaSEli Bendersky 
63174d50731SChris Lattner //===----------------------------------------------------------------------===//
63274d50731SChris Lattner // Check Strings.
63374d50731SChris Lattner //===----------------------------------------------------------------------===//
6343b40b445SChris Lattner 
6354dabac20SChandler Carruth /// A check that we found in the input file.
6363b40b445SChris Lattner struct CheckString {
6374dabac20SChandler Carruth   /// The pattern to match.
6383b40b445SChris Lattner   Pattern Pat;
63926cccfe1SChris Lattner 
6404dabac20SChandler Carruth   /// Which prefix name this check matched.
64113df4626SMatt Arsenault   StringRef Prefix;
64213df4626SMatt Arsenault 
6434dabac20SChandler Carruth   /// The location in the match file that the check string was specified.
64426cccfe1SChris Lattner   SMLoc Loc;
64526cccfe1SChris Lattner 
6464dabac20SChandler Carruth   /// All of the strings that are disallowed from occurring between this match
6474dabac20SChandler Carruth   /// string and the previous one (or start of file).
64891a1b2c9SMichael Liao   std::vector<Pattern> DagNotStrings;
649236d2d5eSChris Lattner 
65085913ccaSJames Y Knight   CheckString(const Pattern &P, StringRef S, SMLoc L)
65185913ccaSJames Y Knight       : Pat(P), Prefix(S), Loc(L) {}
652dcc7d48dSMichael Liao 
653e93a3a08SStephen Lin   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
654f8bd2e5bSStephen Lin                size_t &MatchLen, StringMap<StringRef> &VariableTable) const;
655dcc7d48dSMichael Liao 
656dcc7d48dSMichael Liao   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
65701ac1707SDuncan P. N. Exon Smith   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
658dcc7d48dSMichael Liao   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
65991a1b2c9SMichael Liao                 const std::vector<const Pattern *> &NotStrings,
66091a1b2c9SMichael Liao                 StringMap<StringRef> &VariableTable) const;
66191a1b2c9SMichael Liao   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
66291a1b2c9SMichael Liao                   std::vector<const Pattern *> &NotStrings,
663dcc7d48dSMichael Liao                   StringMap<StringRef> &VariableTable) const;
66426cccfe1SChris Lattner };
66526cccfe1SChris Lattner 
66620247900SChandler Carruth /// Canonicalize whitespaces in the file. Line endings are replaced with
66720247900SChandler Carruth /// UNIX-style '\n'.
668b03c166aSChandler Carruth static StringRef CanonicalizeFile(MemoryBuffer &MB,
66920247900SChandler Carruth                                   SmallVectorImpl<char> &OutputBuffer) {
67020247900SChandler Carruth   OutputBuffer.reserve(MB.getBufferSize());
671a2f8fc5aSChris Lattner 
67220247900SChandler Carruth   for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
673a2f8fc5aSChris Lattner        Ptr != End; ++Ptr) {
674fd781bf0SNAKAMURA Takumi     // Eliminate trailing dosish \r.
675fd781bf0SNAKAMURA Takumi     if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
676fd781bf0SNAKAMURA Takumi       continue;
677fd781bf0SNAKAMURA Takumi     }
678fd781bf0SNAKAMURA Takumi 
6795ea04c38SGuy Benyei     // If current char is not a horizontal whitespace or if horizontal
6805ea04c38SGuy Benyei     // whitespace canonicalization is disabled, dump it to output as is.
681b03c166aSChandler Carruth     if (NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
68220247900SChandler Carruth       OutputBuffer.push_back(*Ptr);
683a2f8fc5aSChris Lattner       continue;
684a2f8fc5aSChris Lattner     }
685a2f8fc5aSChris Lattner 
686a2f8fc5aSChris Lattner     // Otherwise, add one space and advance over neighboring space.
68720247900SChandler Carruth     OutputBuffer.push_back(' ');
688e8f2fb20SChandler Carruth     while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
689a2f8fc5aSChris Lattner       ++Ptr;
690a2f8fc5aSChris Lattner   }
691a2f8fc5aSChris Lattner 
69220247900SChandler Carruth   // Add a null byte and then return all but that byte.
69320247900SChandler Carruth   OutputBuffer.push_back('\0');
69420247900SChandler Carruth   return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
695a2f8fc5aSChris Lattner }
696a2f8fc5aSChris Lattner 
69738820972SMatt Arsenault static bool IsPartOfWord(char c) {
69838820972SMatt Arsenault   return (isalnum(c) || c == '-' || c == '_');
69938820972SMatt Arsenault }
70038820972SMatt Arsenault 
70113df4626SMatt Arsenault // Get the size of the prefix extension.
70213df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) {
70313df4626SMatt Arsenault   switch (Ty) {
70413df4626SMatt Arsenault   case Check::CheckNone:
705a908e7bdSPaul Robinson   case Check::CheckBadNot:
70613df4626SMatt Arsenault     return 0;
70713df4626SMatt Arsenault 
70813df4626SMatt Arsenault   case Check::CheckPlain:
70913df4626SMatt Arsenault     return sizeof(":") - 1;
71013df4626SMatt Arsenault 
71113df4626SMatt Arsenault   case Check::CheckNext:
71213df4626SMatt Arsenault     return sizeof("-NEXT:") - 1;
71313df4626SMatt Arsenault 
71401ac1707SDuncan P. N. Exon Smith   case Check::CheckSame:
71501ac1707SDuncan P. N. Exon Smith     return sizeof("-SAME:") - 1;
71601ac1707SDuncan P. N. Exon Smith 
71713df4626SMatt Arsenault   case Check::CheckNot:
71813df4626SMatt Arsenault     return sizeof("-NOT:") - 1;
71913df4626SMatt Arsenault 
72013df4626SMatt Arsenault   case Check::CheckDAG:
72113df4626SMatt Arsenault     return sizeof("-DAG:") - 1;
72213df4626SMatt Arsenault 
72313df4626SMatt Arsenault   case Check::CheckLabel:
72413df4626SMatt Arsenault     return sizeof("-LABEL:") - 1;
72513df4626SMatt Arsenault 
726*5507f668SJames Henderson   case Check::CheckEmpty:
727*5507f668SJames Henderson     return sizeof("-EMPTY:") - 1;
728*5507f668SJames Henderson 
72913df4626SMatt Arsenault   case Check::CheckEOF:
73013df4626SMatt Arsenault     llvm_unreachable("Should not be using EOF size");
73113df4626SMatt Arsenault   }
73213df4626SMatt Arsenault 
73313df4626SMatt Arsenault   llvm_unreachable("Bad check type");
73413df4626SMatt Arsenault }
73513df4626SMatt Arsenault 
73613df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
73783e63d96SGeorge Rimar   if (Buffer.size() <= Prefix.size())
73883e63d96SGeorge Rimar     return Check::CheckNone;
73983e63d96SGeorge Rimar 
740c4d2d471SMatt Arsenault   char NextChar = Buffer[Prefix.size()];
74138820972SMatt Arsenault 
74238820972SMatt Arsenault   // Verify that the : is present after the prefix.
74313df4626SMatt Arsenault   if (NextChar == ':')
74438820972SMatt Arsenault     return Check::CheckPlain;
74538820972SMatt Arsenault 
74613df4626SMatt Arsenault   if (NextChar != '-')
74738820972SMatt Arsenault     return Check::CheckNone;
74838820972SMatt Arsenault 
749c4d2d471SMatt Arsenault   StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
75013df4626SMatt Arsenault   if (Rest.startswith("NEXT:"))
75138820972SMatt Arsenault     return Check::CheckNext;
75238820972SMatt Arsenault 
75301ac1707SDuncan P. N. Exon Smith   if (Rest.startswith("SAME:"))
75401ac1707SDuncan P. N. Exon Smith     return Check::CheckSame;
75501ac1707SDuncan P. N. Exon Smith 
75613df4626SMatt Arsenault   if (Rest.startswith("NOT:"))
75738820972SMatt Arsenault     return Check::CheckNot;
75838820972SMatt Arsenault 
75913df4626SMatt Arsenault   if (Rest.startswith("DAG:"))
76038820972SMatt Arsenault     return Check::CheckDAG;
76138820972SMatt Arsenault 
76213df4626SMatt Arsenault   if (Rest.startswith("LABEL:"))
76338820972SMatt Arsenault     return Check::CheckLabel;
76413df4626SMatt Arsenault 
765*5507f668SJames Henderson   if (Rest.startswith("EMPTY:"))
766*5507f668SJames Henderson     return Check::CheckEmpty;
767*5507f668SJames Henderson 
768a908e7bdSPaul Robinson   // You can't combine -NOT with another suffix.
769a908e7bdSPaul Robinson   if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
770a908e7bdSPaul Robinson       Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
771*5507f668SJames Henderson       Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
772*5507f668SJames Henderson       Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
773a908e7bdSPaul Robinson     return Check::CheckBadNot;
774a908e7bdSPaul Robinson 
77513df4626SMatt Arsenault   return Check::CheckNone;
77638820972SMatt Arsenault }
77738820972SMatt Arsenault 
77813df4626SMatt Arsenault // From the given position, find the next character after the word.
77913df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) {
78013df4626SMatt Arsenault   while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
78113df4626SMatt Arsenault     ++Loc;
78213df4626SMatt Arsenault   return Loc;
78313df4626SMatt Arsenault }
78413df4626SMatt Arsenault 
785726774cbSChandler Carruth /// Search the buffer for the first prefix in the prefix regular expression.
786726774cbSChandler Carruth ///
787726774cbSChandler Carruth /// This searches the buffer using the provided regular expression, however it
788726774cbSChandler Carruth /// enforces constraints beyond that:
789726774cbSChandler Carruth /// 1) The found prefix must not be a suffix of something that looks like
790726774cbSChandler Carruth ///    a valid prefix.
791726774cbSChandler Carruth /// 2) The found prefix must be followed by a valid check type suffix using \c
792726774cbSChandler Carruth ///    FindCheckType above.
793726774cbSChandler Carruth ///
794726774cbSChandler Carruth /// The first match of the regular expression to satisfy these two is returned,
795726774cbSChandler Carruth /// otherwise an empty StringRef is returned to indicate failure.
796726774cbSChandler Carruth ///
797726774cbSChandler Carruth /// If this routine returns a valid prefix, it will also shrink \p Buffer to
798726774cbSChandler Carruth /// start at the beginning of the returned prefix, increment \p LineNumber for
799726774cbSChandler Carruth /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
800726774cbSChandler Carruth /// check found by examining the suffix.
801726774cbSChandler Carruth ///
802726774cbSChandler Carruth /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
803726774cbSChandler Carruth /// is unspecified.
804726774cbSChandler Carruth static StringRef FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
80513df4626SMatt Arsenault                                          unsigned &LineNumber,
806726774cbSChandler Carruth                                          Check::CheckType &CheckTy) {
807726774cbSChandler Carruth   SmallVector<StringRef, 2> Matches;
808726774cbSChandler Carruth 
80913df4626SMatt Arsenault   while (!Buffer.empty()) {
810726774cbSChandler Carruth     // Find the first (longest) match using the RE.
811726774cbSChandler Carruth     if (!PrefixRE.match(Buffer, &Matches))
812726774cbSChandler Carruth       // No match at all, bail.
813726774cbSChandler Carruth       return StringRef();
814726774cbSChandler Carruth 
815726774cbSChandler Carruth     StringRef Prefix = Matches[0];
816726774cbSChandler Carruth     Matches.clear();
817726774cbSChandler Carruth 
818726774cbSChandler Carruth     assert(Prefix.data() >= Buffer.data() &&
819726774cbSChandler Carruth            Prefix.data() < Buffer.data() + Buffer.size() &&
820726774cbSChandler Carruth            "Prefix doesn't start inside of buffer!");
821726774cbSChandler Carruth     size_t Loc = Prefix.data() - Buffer.data();
822726774cbSChandler Carruth     StringRef Skipped = Buffer.substr(0, Loc);
823726774cbSChandler Carruth     Buffer = Buffer.drop_front(Loc);
824726774cbSChandler Carruth     LineNumber += Skipped.count('\n');
825726774cbSChandler Carruth 
826726774cbSChandler Carruth     // Check that the matched prefix isn't a suffix of some other check-like
827726774cbSChandler Carruth     // word.
828726774cbSChandler Carruth     // FIXME: This is a very ad-hoc check. it would be better handled in some
829726774cbSChandler Carruth     // other way. Among other things it seems hard to distinguish between
830726774cbSChandler Carruth     // intentional and unintentional uses of this feature.
831726774cbSChandler Carruth     if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
832726774cbSChandler Carruth       // Now extract the type.
833726774cbSChandler Carruth       CheckTy = FindCheckType(Buffer, Prefix);
834726774cbSChandler Carruth 
835726774cbSChandler Carruth       // If we've found a valid check type for this prefix, we're done.
836726774cbSChandler Carruth       if (CheckTy != Check::CheckNone)
83713df4626SMatt Arsenault         return Prefix;
83813df4626SMatt Arsenault     }
83913df4626SMatt Arsenault 
840726774cbSChandler Carruth     // If we didn't successfully find a prefix, we need to skip this invalid
841726774cbSChandler Carruth     // prefix and continue scanning. We directly skip the prefix that was
842726774cbSChandler Carruth     // matched and any additional parts of that check-like word.
843726774cbSChandler Carruth     Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
84413df4626SMatt Arsenault   }
84513df4626SMatt Arsenault 
846726774cbSChandler Carruth   // We ran out of buffer while skipping partial matches so give up.
84713df4626SMatt Arsenault   return StringRef();
84838820972SMatt Arsenault }
849ee3c74fbSChris Lattner 
8504dabac20SChandler Carruth /// Read the check file, which specifies the sequence of expected strings.
8514dabac20SChandler Carruth ///
8524dabac20SChandler Carruth /// The strings are added to the CheckStrings vector. Returns true in case of
8534dabac20SChandler Carruth /// an error, false otherwise.
854726774cbSChandler Carruth static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
85526cccfe1SChris Lattner                           std::vector<CheckString> &CheckStrings) {
85656ccdbbdSAlexander Kornienko   std::vector<Pattern> ImplicitNegativeChecks;
85756ccdbbdSAlexander Kornienko   for (const auto &PatternString : ImplicitCheckNot) {
85856ccdbbdSAlexander Kornienko     // Create a buffer with fake command line content in order to display the
85956ccdbbdSAlexander Kornienko     // command line option responsible for the specific implicit CHECK-NOT.
860ff43d69dSDavid Blaikie     std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str();
86156ccdbbdSAlexander Kornienko     std::string Suffix = "'";
8623560ff2cSRafael Espindola     std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
8633560ff2cSRafael Espindola         Prefix + PatternString + Suffix, "command line");
8643560ff2cSRafael Espindola 
86556ccdbbdSAlexander Kornienko     StringRef PatternInBuffer =
86656ccdbbdSAlexander Kornienko         CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
8671961f14cSDavid Blaikie     SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
86856ccdbbdSAlexander Kornienko 
86956ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot));
87056ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
87156ccdbbdSAlexander Kornienko                                                "IMPLICIT-CHECK", SM, 0);
87256ccdbbdSAlexander Kornienko   }
87356ccdbbdSAlexander Kornienko 
87456ccdbbdSAlexander Kornienko   std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
875236d2d5eSChris Lattner 
87643d50d4aSEli Bendersky   // LineNumber keeps track of the line on which CheckPrefix instances are
87743d50d4aSEli Bendersky   // found.
87892987fb3SAlexander Kornienko   unsigned LineNumber = 1;
87992987fb3SAlexander Kornienko 
880ee3c74fbSChris Lattner   while (1) {
88113df4626SMatt Arsenault     Check::CheckType CheckTy;
88213df4626SMatt Arsenault 
88313df4626SMatt Arsenault     // See if a prefix occurs in the memory buffer.
884726774cbSChandler Carruth     StringRef UsedPrefix = FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber,
885726774cbSChandler Carruth                                                    CheckTy);
88613df4626SMatt Arsenault     if (UsedPrefix.empty())
887ee3c74fbSChris Lattner       break;
888726774cbSChandler Carruth     assert(UsedPrefix.data() == Buffer.data() &&
889726774cbSChandler Carruth            "Failed to move Buffer's start forward, or pointed prefix outside "
890726774cbSChandler Carruth            "of the buffer!");
89192987fb3SAlexander Kornienko 
89213df4626SMatt Arsenault     // Location to use for error messages.
893726774cbSChandler Carruth     const char *UsedPrefixStart = UsedPrefix.data();
89492987fb3SAlexander Kornienko 
895726774cbSChandler Carruth     // Skip the buffer to the end.
89613df4626SMatt Arsenault     Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
89710f10cedSChris Lattner 
898a908e7bdSPaul Robinson     // Complain about useful-looking but unsupported suffixes.
899a908e7bdSPaul Robinson     if (CheckTy == Check::CheckBadNot) {
900e8f2fb20SChandler Carruth       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
901a908e7bdSPaul Robinson                       "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
902a908e7bdSPaul Robinson       return true;
903a908e7bdSPaul Robinson     }
904a908e7bdSPaul Robinson 
90538820972SMatt Arsenault     // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
906a26bc914STom de Vries     // leading whitespace.
9071714676aSTom de Vries     if (!(NoCanonicalizeWhiteSpace && MatchFullLines))
908236d2d5eSChris Lattner       Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
909ee3c74fbSChris Lattner 
910ee3c74fbSChris Lattner     // Scan ahead to the end of line.
911caa5fc0cSChris Lattner     size_t EOL = Buffer.find_first_of("\n\r");
912ee3c74fbSChris Lattner 
913838fb09aSDan Gohman     // Remember the location of the start of the pattern, for diagnostics.
914838fb09aSDan Gohman     SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
915838fb09aSDan Gohman 
91674d50731SChris Lattner     // Parse the pattern.
91738820972SMatt Arsenault     Pattern P(CheckTy);
91813df4626SMatt Arsenault     if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber))
919ee3c74fbSChris Lattner       return true;
920ee3c74fbSChris Lattner 
921f8bd2e5bSStephen Lin     // Verify that CHECK-LABEL lines do not define or use variables
92238820972SMatt Arsenault     if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
923e8f2fb20SChandler Carruth       SM.PrintMessage(
924e8f2fb20SChandler Carruth           SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
92513df4626SMatt Arsenault           "found '" + UsedPrefix + "-LABEL:'"
92613df4626SMatt Arsenault                                    " with variable definition or use");
927f8bd2e5bSStephen Lin       return true;
928f8bd2e5bSStephen Lin     }
929f8bd2e5bSStephen Lin 
930236d2d5eSChris Lattner     Buffer = Buffer.substr(EOL);
93174d50731SChris Lattner 
932*5507f668SJames Henderson     // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
933*5507f668SJames Henderson     if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
934*5507f668SJames Henderson          CheckTy == Check::CheckEmpty) &&
93501ac1707SDuncan P. N. Exon Smith         CheckStrings.empty()) {
936*5507f668SJames Henderson       StringRef Type = CheckTy == Check::CheckNext
937*5507f668SJames Henderson                            ? "NEXT"
938*5507f668SJames Henderson                            : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
93913df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
94003b80a40SChris Lattner                       SourceMgr::DK_Error,
941e8f2fb20SChandler Carruth                       "found '" + UsedPrefix + "-" + Type +
942e8f2fb20SChandler Carruth                           "' without previous '" + UsedPrefix + ": line");
943da108b4eSChris Lattner       return true;
944da108b4eSChris Lattner     }
945da108b4eSChris Lattner 
94691a1b2c9SMichael Liao     // Handle CHECK-DAG/-NOT.
94738820972SMatt Arsenault     if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
94891a1b2c9SMichael Liao       DagNotMatches.push_back(P);
94974d50731SChris Lattner       continue;
95074d50731SChris Lattner     }
95174d50731SChris Lattner 
952ee3c74fbSChris Lattner     // Okay, add the string we captured to the output vector and move on.
95385913ccaSJames Y Knight     CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
95491a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
95556ccdbbdSAlexander Kornienko     DagNotMatches = ImplicitNegativeChecks;
956ee3c74fbSChris Lattner   }
957ee3c74fbSChris Lattner 
95813df4626SMatt Arsenault   // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
95913df4626SMatt Arsenault   // prefix as a filler for the error message.
96091a1b2c9SMichael Liao   if (!DagNotMatches.empty()) {
961f5e2fc47SBenjamin Kramer     CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(),
96285913ccaSJames Y Knight                               SMLoc::getFromPointer(Buffer.data()));
96391a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
964eba55822SJakob Stoklund Olesen   }
965eba55822SJakob Stoklund Olesen 
966ee3c74fbSChris Lattner   if (CheckStrings.empty()) {
96713df4626SMatt Arsenault     errs() << "error: no check strings found with prefix"
96813df4626SMatt Arsenault            << (CheckPrefixes.size() > 1 ? "es " : " ");
9693e3ef2f2SChris Bieneman     prefix_iterator I = CheckPrefixes.begin();
9703e3ef2f2SChris Bieneman     prefix_iterator E = CheckPrefixes.end();
9713e3ef2f2SChris Bieneman     if (I != E) {
9723e3ef2f2SChris Bieneman       errs() << "\'" << *I << ":'";
9733e3ef2f2SChris Bieneman       ++I;
97413df4626SMatt Arsenault     }
9753e3ef2f2SChris Bieneman     for (; I != E; ++I)
9763e3ef2f2SChris Bieneman       errs() << ", \'" << *I << ":'";
97713df4626SMatt Arsenault 
97813df4626SMatt Arsenault     errs() << '\n';
979ee3c74fbSChris Lattner     return true;
980ee3c74fbSChris Lattner   }
981ee3c74fbSChris Lattner 
982ee3c74fbSChris Lattner   return false;
983ee3c74fbSChris Lattner }
984ee3c74fbSChris Lattner 
985e8f2fb20SChandler Carruth static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
986e8f2fb20SChandler Carruth                              StringRef Buffer,
987e0ef65abSDaniel Dunbar                              StringMap<StringRef> &VariableTable) {
988da108b4eSChris Lattner   // Otherwise, we have an error, emit an error message.
98991a1b2c9SMichael Liao   SM.PrintMessage(Loc, SourceMgr::DK_Error,
99003b80a40SChris Lattner                   "expected string not found in input");
991da108b4eSChris Lattner 
992da108b4eSChris Lattner   // Print the "scanning from here" line.  If the current position is at the
993da108b4eSChris Lattner   // end of a line, advance to the start of the next line.
994caa5fc0cSChris Lattner   Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
995da108b4eSChris Lattner 
99603b80a40SChris Lattner   SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
99703b80a40SChris Lattner                   "scanning from here");
998e0ef65abSDaniel Dunbar 
999e0ef65abSDaniel Dunbar   // Allow the pattern to print additional information if desired.
100091a1b2c9SMichael Liao   Pat.PrintFailureInfo(SM, Buffer, VariableTable);
100191a1b2c9SMichael Liao }
100291a1b2c9SMichael Liao 
100391a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
100491a1b2c9SMichael Liao                              StringRef Buffer,
100591a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) {
100691a1b2c9SMichael Liao   PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
1007da108b4eSChris Lattner }
1008da108b4eSChris Lattner 
10094dabac20SChandler Carruth /// Count the number of newlines in the specified range.
1010592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range,
1011592fe880SRichard Smith                                         const char *&FirstNewLine) {
1012da108b4eSChris Lattner   unsigned NumNewLines = 0;
101337183584SChris Lattner   while (1) {
1014da108b4eSChris Lattner     // Scan for newline.
101537183584SChris Lattner     Range = Range.substr(Range.find_first_of("\n\r"));
1016e8f2fb20SChandler Carruth     if (Range.empty())
1017e8f2fb20SChandler Carruth       return NumNewLines;
1018da108b4eSChris Lattner 
1019da108b4eSChris Lattner     ++NumNewLines;
1020da108b4eSChris Lattner 
1021da108b4eSChris Lattner     // Handle \n\r and \r\n as a single newline.
1022e8f2fb20SChandler Carruth     if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
102337183584SChris Lattner         (Range[0] != Range[1]))
102437183584SChris Lattner       Range = Range.substr(1);
102537183584SChris Lattner     Range = Range.substr(1);
1026592fe880SRichard Smith 
1027592fe880SRichard Smith     if (NumNewLines == 1)
1028592fe880SRichard Smith       FirstNewLine = Range.begin();
1029da108b4eSChris Lattner   }
1030da108b4eSChris Lattner }
1031da108b4eSChris Lattner 
10324dabac20SChandler Carruth /// Match check string and its "not strings" and/or "dag strings".
1033dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
1034e93a3a08SStephen Lin                           bool IsLabelScanMode, size_t &MatchLen,
1035dcc7d48dSMichael Liao                           StringMap<StringRef> &VariableTable) const {
103691a1b2c9SMichael Liao   size_t LastPos = 0;
103791a1b2c9SMichael Liao   std::vector<const Pattern *> NotStrings;
103891a1b2c9SMichael Liao 
1039e93a3a08SStephen Lin   // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1040e93a3a08SStephen Lin   // bounds; we have not processed variable definitions within the bounded block
1041e93a3a08SStephen Lin   // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1042e93a3a08SStephen Lin   // over the block again (including the last CHECK-LABEL) in normal mode.
1043e93a3a08SStephen Lin   if (!IsLabelScanMode) {
104491a1b2c9SMichael Liao     // Match "dag strings" (with mixed "not strings" if any).
104591a1b2c9SMichael Liao     LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable);
104691a1b2c9SMichael Liao     if (LastPos == StringRef::npos)
104791a1b2c9SMichael Liao       return StringRef::npos;
1048e93a3a08SStephen Lin   }
104991a1b2c9SMichael Liao 
105091a1b2c9SMichael Liao   // Match itself from the last position after matching CHECK-DAG.
105191a1b2c9SMichael Liao   StringRef MatchBuffer = Buffer.substr(LastPos);
105291a1b2c9SMichael Liao   size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
1053dcc7d48dSMichael Liao   if (MatchPos == StringRef::npos) {
105491a1b2c9SMichael Liao     PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
1055dcc7d48dSMichael Liao     return StringRef::npos;
1056dcc7d48dSMichael Liao   }
1057dcc7d48dSMichael Liao 
1058e93a3a08SStephen Lin   // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1059e93a3a08SStephen Lin   // or CHECK-NOT
1060e93a3a08SStephen Lin   if (!IsLabelScanMode) {
106191a1b2c9SMichael Liao     StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1062dcc7d48dSMichael Liao 
1063dcc7d48dSMichael Liao     // If this check is a "CHECK-NEXT", verify that the previous match was on
1064dcc7d48dSMichael Liao     // the previous line (i.e. that there is one newline between them).
1065dcc7d48dSMichael Liao     if (CheckNext(SM, SkippedRegion))
1066dcc7d48dSMichael Liao       return StringRef::npos;
1067dcc7d48dSMichael Liao 
106801ac1707SDuncan P. N. Exon Smith     // If this check is a "CHECK-SAME", verify that the previous match was on
106901ac1707SDuncan P. N. Exon Smith     // the same line (i.e. that there is no newline between them).
107001ac1707SDuncan P. N. Exon Smith     if (CheckSame(SM, SkippedRegion))
107101ac1707SDuncan P. N. Exon Smith       return StringRef::npos;
107201ac1707SDuncan P. N. Exon Smith 
1073dcc7d48dSMichael Liao     // If this match had "not strings", verify that they don't exist in the
1074dcc7d48dSMichael Liao     // skipped region.
107591a1b2c9SMichael Liao     if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
1076dcc7d48dSMichael Liao       return StringRef::npos;
1077f8bd2e5bSStephen Lin   }
1078dcc7d48dSMichael Liao 
10797dfb92b9SMehdi Amini   return LastPos + MatchPos;
1080dcc7d48dSMichael Liao }
1081dcc7d48dSMichael Liao 
10824dabac20SChandler Carruth /// Verify there is a single line in the given buffer.
1083dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
1084*5507f668SJames Henderson   if (Pat.getCheckTy() != Check::CheckNext &&
1085*5507f668SJames Henderson       Pat.getCheckTy() != Check::CheckEmpty)
1086dcc7d48dSMichael Liao     return false;
1087dcc7d48dSMichael Liao 
1088*5507f668SJames Henderson   Twine CheckName =
1089*5507f668SJames Henderson       Prefix +
1090*5507f668SJames Henderson       Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
1091*5507f668SJames Henderson 
1092dcc7d48dSMichael Liao   // Count the number of newlines between the previous match and this one.
1093dcc7d48dSMichael Liao   assert(Buffer.data() !=
1094e8f2fb20SChandler Carruth              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
1095e8f2fb20SChandler Carruth                                     SMLoc::getFromPointer(Buffer.data())))
1096e8f2fb20SChandler Carruth                  ->getBufferStart() &&
1097*5507f668SJames Henderson          "CHECK-NEXT and CHECK-EMPTY can't be the first check in a file");
1098dcc7d48dSMichael Liao 
109966f09ad0SCraig Topper   const char *FirstNewLine = nullptr;
1100592fe880SRichard Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1101dcc7d48dSMichael Liao 
1102*5507f668SJames Henderson   // For CHECK-EMPTY, the preceding new line is consumed by the pattern, so
1103*5507f668SJames Henderson   // this needs to be re-added.
1104*5507f668SJames Henderson   if (Pat.getCheckTy() == Check::CheckEmpty)
1105*5507f668SJames Henderson     ++NumNewLines;
1106*5507f668SJames Henderson 
1107dcc7d48dSMichael Liao   if (NumNewLines == 0) {
1108e8f2fb20SChandler Carruth     SM.PrintMessage(Loc, SourceMgr::DK_Error,
1109*5507f668SJames Henderson                     CheckName + ": is on the same line as previous match");
1110e8f2fb20SChandler Carruth     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1111e8f2fb20SChandler Carruth                     "'next' match was here");
1112dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1113dcc7d48dSMichael Liao                     "previous match ended here");
1114dcc7d48dSMichael Liao     return true;
1115dcc7d48dSMichael Liao   }
1116dcc7d48dSMichael Liao 
1117dcc7d48dSMichael Liao   if (NumNewLines != 1) {
1118e8f2fb20SChandler Carruth     SM.PrintMessage(Loc, SourceMgr::DK_Error,
1119*5507f668SJames Henderson                     CheckName +
1120*5507f668SJames Henderson                         ": is not on the line after the previous match");
1121e8f2fb20SChandler Carruth     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1122e8f2fb20SChandler Carruth                     "'next' match was here");
1123dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1124dcc7d48dSMichael Liao                     "previous match ended here");
1125592fe880SRichard Smith     SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
1126592fe880SRichard Smith                     "non-matching line after previous match is here");
1127dcc7d48dSMichael Liao     return true;
1128dcc7d48dSMichael Liao   }
1129dcc7d48dSMichael Liao 
1130dcc7d48dSMichael Liao   return false;
1131dcc7d48dSMichael Liao }
1132dcc7d48dSMichael Liao 
11334dabac20SChandler Carruth /// Verify there is no newline in the given buffer.
113401ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
113585913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckSame)
113601ac1707SDuncan P. N. Exon Smith     return false;
113701ac1707SDuncan P. N. Exon Smith 
113801ac1707SDuncan P. N. Exon Smith   // Count the number of newlines between the previous match and this one.
113901ac1707SDuncan P. N. Exon Smith   assert(Buffer.data() !=
114001ac1707SDuncan P. N. Exon Smith              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
114101ac1707SDuncan P. N. Exon Smith                                     SMLoc::getFromPointer(Buffer.data())))
114201ac1707SDuncan P. N. Exon Smith                  ->getBufferStart() &&
114301ac1707SDuncan P. N. Exon Smith          "CHECK-SAME can't be the first check in a file");
114401ac1707SDuncan P. N. Exon Smith 
114501ac1707SDuncan P. N. Exon Smith   const char *FirstNewLine = nullptr;
114601ac1707SDuncan P. N. Exon Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
114701ac1707SDuncan P. N. Exon Smith 
114801ac1707SDuncan P. N. Exon Smith   if (NumNewLines != 0) {
114901ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(Loc, SourceMgr::DK_Error,
115001ac1707SDuncan P. N. Exon Smith                     Prefix +
115101ac1707SDuncan P. N. Exon Smith                         "-SAME: is not on the same line as the previous match");
115201ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
115301ac1707SDuncan P. N. Exon Smith                     "'next' match was here");
115401ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
115501ac1707SDuncan P. N. Exon Smith                     "previous match ended here");
115601ac1707SDuncan P. N. Exon Smith     return true;
115701ac1707SDuncan P. N. Exon Smith   }
115801ac1707SDuncan P. N. Exon Smith 
115901ac1707SDuncan P. N. Exon Smith   return false;
116001ac1707SDuncan P. N. Exon Smith }
116101ac1707SDuncan P. N. Exon Smith 
11624dabac20SChandler Carruth /// Verify there's no "not strings" in the given buffer.
1163dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
116491a1b2c9SMichael Liao                            const std::vector<const Pattern *> &NotStrings,
1165dcc7d48dSMichael Liao                            StringMap<StringRef> &VariableTable) const {
11668f870499SBenjamin Kramer   for (const Pattern *Pat : NotStrings) {
116738820972SMatt Arsenault     assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
116891a1b2c9SMichael Liao 
1169dcc7d48dSMichael Liao     size_t MatchLen = 0;
117091a1b2c9SMichael Liao     size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
1171dcc7d48dSMichael Liao 
1172e8f2fb20SChandler Carruth     if (Pos == StringRef::npos)
1173e8f2fb20SChandler Carruth       continue;
1174dcc7d48dSMichael Liao 
1175dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos),
1176e8f2fb20SChandler Carruth                     SourceMgr::DK_Error, Prefix + "-NOT: string occurred!");
117791a1b2c9SMichael Liao     SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
117813df4626SMatt Arsenault                     Prefix + "-NOT: pattern specified here");
1179dcc7d48dSMichael Liao     return true;
1180dcc7d48dSMichael Liao   }
1181dcc7d48dSMichael Liao 
1182dcc7d48dSMichael Liao   return false;
1183dcc7d48dSMichael Liao }
1184dcc7d48dSMichael Liao 
11854dabac20SChandler Carruth /// Match "dag strings" and their mixed "not strings".
118691a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
118791a1b2c9SMichael Liao                              std::vector<const Pattern *> &NotStrings,
118891a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) const {
118991a1b2c9SMichael Liao   if (DagNotStrings.empty())
119091a1b2c9SMichael Liao     return 0;
119191a1b2c9SMichael Liao 
119291a1b2c9SMichael Liao   size_t LastPos = 0;
119391a1b2c9SMichael Liao   size_t StartPos = LastPos;
119491a1b2c9SMichael Liao 
11958f870499SBenjamin Kramer   for (const Pattern &Pat : DagNotStrings) {
119638820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG ||
119738820972SMatt Arsenault             Pat.getCheckTy() == Check::CheckNot) &&
119891a1b2c9SMichael Liao            "Invalid CHECK-DAG or CHECK-NOT!");
119991a1b2c9SMichael Liao 
120038820972SMatt Arsenault     if (Pat.getCheckTy() == Check::CheckNot) {
120191a1b2c9SMichael Liao       NotStrings.push_back(&Pat);
120291a1b2c9SMichael Liao       continue;
120391a1b2c9SMichael Liao     }
120491a1b2c9SMichael Liao 
120538820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
120691a1b2c9SMichael Liao 
120791a1b2c9SMichael Liao     size_t MatchLen = 0, MatchPos;
120891a1b2c9SMichael Liao 
120991a1b2c9SMichael Liao     // CHECK-DAG always matches from the start.
121091a1b2c9SMichael Liao     StringRef MatchBuffer = Buffer.substr(StartPos);
121191a1b2c9SMichael Liao     MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
121291a1b2c9SMichael Liao     // With a group of CHECK-DAGs, a single mismatching means the match on
121391a1b2c9SMichael Liao     // that group of CHECK-DAGs fails immediately.
121491a1b2c9SMichael Liao     if (MatchPos == StringRef::npos) {
121591a1b2c9SMichael Liao       PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
121691a1b2c9SMichael Liao       return StringRef::npos;
121791a1b2c9SMichael Liao     }
121891a1b2c9SMichael Liao     // Re-calc it as the offset relative to the start of the original string.
121991a1b2c9SMichael Liao     MatchPos += StartPos;
122091a1b2c9SMichael Liao 
122191a1b2c9SMichael Liao     if (!NotStrings.empty()) {
122291a1b2c9SMichael Liao       if (MatchPos < LastPos) {
122391a1b2c9SMichael Liao         // Reordered?
122491a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
122591a1b2c9SMichael Liao                         SourceMgr::DK_Error,
122613df4626SMatt Arsenault                         Prefix + "-DAG: found a match of CHECK-DAG"
122791a1b2c9SMichael Liao                                  " reordering across a CHECK-NOT");
122891a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
122991a1b2c9SMichael Liao                         SourceMgr::DK_Note,
123013df4626SMatt Arsenault                         Prefix + "-DAG: the farthest match of CHECK-DAG"
123191a1b2c9SMichael Liao                                  " is found here");
123291a1b2c9SMichael Liao         SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
123313df4626SMatt Arsenault                         Prefix + "-NOT: the crossed pattern specified"
123491a1b2c9SMichael Liao                                  " here");
123591a1b2c9SMichael Liao         SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
123613df4626SMatt Arsenault                         Prefix + "-DAG: the reordered pattern specified"
123791a1b2c9SMichael Liao                                  " here");
123891a1b2c9SMichael Liao         return StringRef::npos;
123991a1b2c9SMichael Liao       }
124091a1b2c9SMichael Liao       // All subsequent CHECK-DAGs should be matched from the farthest
124191a1b2c9SMichael Liao       // position of all precedent CHECK-DAGs (including this one.)
124291a1b2c9SMichael Liao       StartPos = LastPos;
124391a1b2c9SMichael Liao       // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
124491a1b2c9SMichael Liao       // CHECK-DAG, verify that there's no 'not' strings occurred in that
124591a1b2c9SMichael Liao       // region.
1246cf60ab31SBenjamin Kramer       StringRef SkippedRegion = Buffer.slice(LastPos, MatchPos);
1247cf708c32STim Northover       if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
124891a1b2c9SMichael Liao         return StringRef::npos;
124991a1b2c9SMichael Liao       // Clear "not strings".
125091a1b2c9SMichael Liao       NotStrings.clear();
125191a1b2c9SMichael Liao     }
125291a1b2c9SMichael Liao 
125391a1b2c9SMichael Liao     // Update the last position with CHECK-DAG matches.
125491a1b2c9SMichael Liao     LastPos = std::max(MatchPos + MatchLen, LastPos);
125591a1b2c9SMichael Liao   }
125691a1b2c9SMichael Liao 
125791a1b2c9SMichael Liao   return LastPos;
125891a1b2c9SMichael Liao }
125991a1b2c9SMichael Liao 
126013df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores.
126113df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) {
126213df4626SMatt Arsenault   Regex Validator("^[a-zA-Z0-9_-]*$");
126313df4626SMatt Arsenault   return Validator.match(CheckPrefix);
126413df4626SMatt Arsenault }
126513df4626SMatt Arsenault 
126613df4626SMatt Arsenault static bool ValidateCheckPrefixes() {
126713df4626SMatt Arsenault   StringSet<> PrefixSet;
126813df4626SMatt Arsenault 
12698f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
127024412b14SEli Bendersky     // Reject empty prefixes.
127124412b14SEli Bendersky     if (Prefix == "")
127224412b14SEli Bendersky       return false;
127324412b14SEli Bendersky 
12740356975cSDavid Blaikie     if (!PrefixSet.insert(Prefix).second)
127513df4626SMatt Arsenault       return false;
127613df4626SMatt Arsenault 
127713df4626SMatt Arsenault     if (!ValidateCheckPrefix(Prefix))
127813df4626SMatt Arsenault       return false;
127913df4626SMatt Arsenault   }
128013df4626SMatt Arsenault 
128113df4626SMatt Arsenault   return true;
128213df4626SMatt Arsenault }
128313df4626SMatt Arsenault 
1284726774cbSChandler Carruth // Combines the check prefixes into a single regex so that we can efficiently
1285726774cbSChandler Carruth // scan for any of the set.
1286726774cbSChandler Carruth //
1287726774cbSChandler Carruth // The semantics are that the longest-match wins which matches our regex
1288726774cbSChandler Carruth // library.
1289726774cbSChandler Carruth static Regex buildCheckPrefixRegex() {
129013df4626SMatt Arsenault   // I don't think there's a way to specify an initial value for cl::list,
129113df4626SMatt Arsenault   // so if nothing was specified, add the default
129213df4626SMatt Arsenault   if (CheckPrefixes.empty())
129313df4626SMatt Arsenault     CheckPrefixes.push_back("CHECK");
1294726774cbSChandler Carruth 
1295726774cbSChandler Carruth   // We already validated the contents of CheckPrefixes so just concatenate
1296726774cbSChandler Carruth   // them as alternatives.
1297726774cbSChandler Carruth   SmallString<32> PrefixRegexStr;
1298726774cbSChandler Carruth   for (StringRef Prefix : CheckPrefixes) {
1299726774cbSChandler Carruth     if (Prefix != CheckPrefixes.front())
1300726774cbSChandler Carruth       PrefixRegexStr.push_back('|');
1301726774cbSChandler Carruth 
1302726774cbSChandler Carruth     PrefixRegexStr.append(Prefix);
1303726774cbSChandler Carruth   }
1304726774cbSChandler Carruth 
1305726774cbSChandler Carruth   return Regex(PrefixRegexStr);
1306c2735158SRui Ueyama }
1307c2735158SRui Ueyama 
13082bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) {
13092bd4f8b6SXinliang David Li   errs() << "FileCheck command line: ";
13102bd4f8b6SXinliang David Li   for (int I = 0; I < argc; I++)
13112bd4f8b6SXinliang David Li     errs() << " " << argv[I];
13122bd4f8b6SXinliang David Li   errs() << "\n";
13132bd4f8b6SXinliang David Li }
13142bd4f8b6SXinliang David Li 
1315f55e72a5SArtem Belevich // Remove local variables from \p VariableTable. Global variables
1316f55e72a5SArtem Belevich // (start with '$') are preserved.
1317f55e72a5SArtem Belevich static void ClearLocalVars(StringMap<StringRef> &VariableTable) {
1318f55e72a5SArtem Belevich   SmallVector<StringRef, 16> LocalVars;
1319f55e72a5SArtem Belevich   for (const auto &Var : VariableTable)
1320f55e72a5SArtem Belevich     if (Var.first()[0] != '$')
1321f55e72a5SArtem Belevich       LocalVars.push_back(Var.first());
1322f55e72a5SArtem Belevich 
1323f55e72a5SArtem Belevich   for (const auto &Var : LocalVars)
1324f55e72a5SArtem Belevich     VariableTable.erase(Var);
1325f55e72a5SArtem Belevich }
1326f55e72a5SArtem Belevich 
132720247900SChandler Carruth /// Check the input to FileCheck provided in the \p Buffer against the \p
132820247900SChandler Carruth /// CheckStrings read from the check file.
132920247900SChandler Carruth ///
133020247900SChandler Carruth /// Returns false if the input fails to satisfy the checks.
133120247900SChandler Carruth bool CheckInput(SourceMgr &SM, StringRef Buffer,
133220247900SChandler Carruth                 ArrayRef<CheckString> CheckStrings) {
133320247900SChandler Carruth   bool ChecksFailed = false;
133420247900SChandler Carruth 
133520247900SChandler Carruth   /// VariableTable - This holds all the current filecheck variables.
133620247900SChandler Carruth   StringMap<StringRef> VariableTable;
133720247900SChandler Carruth 
133846e1fd61SAlexander Richardson   for (const auto& Def : GlobalDefines)
133946e1fd61SAlexander Richardson     VariableTable.insert(StringRef(Def).split('='));
134046e1fd61SAlexander Richardson 
134120247900SChandler Carruth   unsigned i = 0, j = 0, e = CheckStrings.size();
134220247900SChandler Carruth   while (true) {
134320247900SChandler Carruth     StringRef CheckRegion;
134420247900SChandler Carruth     if (j == e) {
134520247900SChandler Carruth       CheckRegion = Buffer;
134620247900SChandler Carruth     } else {
134720247900SChandler Carruth       const CheckString &CheckLabelStr = CheckStrings[j];
134820247900SChandler Carruth       if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
134920247900SChandler Carruth         ++j;
135020247900SChandler Carruth         continue;
135120247900SChandler Carruth       }
135220247900SChandler Carruth 
135320247900SChandler Carruth       // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
135420247900SChandler Carruth       size_t MatchLabelLen = 0;
1355e8f2fb20SChandler Carruth       size_t MatchLabelPos =
1356e8f2fb20SChandler Carruth           CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, VariableTable);
135720247900SChandler Carruth       if (MatchLabelPos == StringRef::npos)
135820247900SChandler Carruth         // Immediately bail of CHECK-LABEL fails, nothing else we can do.
135920247900SChandler Carruth         return false;
136020247900SChandler Carruth 
136120247900SChandler Carruth       CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
136220247900SChandler Carruth       Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
136320247900SChandler Carruth       ++j;
136420247900SChandler Carruth     }
136520247900SChandler Carruth 
1366f55e72a5SArtem Belevich     if (EnableVarScope)
1367f55e72a5SArtem Belevich       ClearLocalVars(VariableTable);
1368f55e72a5SArtem Belevich 
136920247900SChandler Carruth     for (; i != j; ++i) {
137020247900SChandler Carruth       const CheckString &CheckStr = CheckStrings[i];
137120247900SChandler Carruth 
137220247900SChandler Carruth       // Check each string within the scanned region, including a second check
137320247900SChandler Carruth       // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
137420247900SChandler Carruth       size_t MatchLen = 0;
1375e8f2fb20SChandler Carruth       size_t MatchPos =
1376e8f2fb20SChandler Carruth           CheckStr.Check(SM, CheckRegion, false, MatchLen, VariableTable);
137720247900SChandler Carruth 
137820247900SChandler Carruth       if (MatchPos == StringRef::npos) {
137920247900SChandler Carruth         ChecksFailed = true;
138020247900SChandler Carruth         i = j;
138120247900SChandler Carruth         break;
138220247900SChandler Carruth       }
138320247900SChandler Carruth 
138420247900SChandler Carruth       CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
138520247900SChandler Carruth     }
138620247900SChandler Carruth 
138720247900SChandler Carruth     if (j == e)
138820247900SChandler Carruth       break;
138920247900SChandler Carruth   }
139020247900SChandler Carruth 
139120247900SChandler Carruth   // Success if no checks failed.
139220247900SChandler Carruth   return !ChecksFailed;
139320247900SChandler Carruth }
139420247900SChandler Carruth 
1395ee3c74fbSChris Lattner int main(int argc, char **argv) {
1396197194b6SRui Ueyama   InitLLVM X(argc, argv);
1397ee3c74fbSChris Lattner   cl::ParseCommandLineOptions(argc, argv);
1398ee3c74fbSChris Lattner 
139913df4626SMatt Arsenault   if (!ValidateCheckPrefixes()) {
140013df4626SMatt Arsenault     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
140113df4626SMatt Arsenault               "start with a letter and contain only alphanumeric characters, "
140213df4626SMatt Arsenault               "hyphens and underscores\n";
1403c2735158SRui Ueyama     return 2;
1404c2735158SRui Ueyama   }
1405c2735158SRui Ueyama 
1406726774cbSChandler Carruth   Regex PrefixRE = buildCheckPrefixRegex();
1407726774cbSChandler Carruth   std::string REError;
1408726774cbSChandler Carruth   if (!PrefixRE.isValid(REError)) {
1409726774cbSChandler Carruth     errs() << "Unable to combine check-prefix strings into a prefix regular "
1410726774cbSChandler Carruth               "expression! This is likely a bug in FileCheck's verification of "
1411726774cbSChandler Carruth               "the check-prefix strings. Regular expression parsing failed "
1412726774cbSChandler Carruth               "with the following error: "
1413726774cbSChandler Carruth            << REError << "\n";
1414726774cbSChandler Carruth     return 2;
1415726774cbSChandler Carruth   }
141613df4626SMatt Arsenault 
1417ee3c74fbSChris Lattner   SourceMgr SM;
1418ee3c74fbSChris Lattner 
1419ee3c74fbSChris Lattner   // Read the expected strings from the check file.
142020247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
142120247900SChandler Carruth       MemoryBuffer::getFileOrSTDIN(CheckFilename);
142220247900SChandler Carruth   if (std::error_code EC = CheckFileOrErr.getError()) {
142320247900SChandler Carruth     errs() << "Could not open check file '" << CheckFilename
142420247900SChandler Carruth            << "': " << EC.message() << '\n';
142520247900SChandler Carruth     return 2;
142620247900SChandler Carruth   }
142720247900SChandler Carruth   MemoryBuffer &CheckFile = *CheckFileOrErr.get();
142820247900SChandler Carruth 
142920247900SChandler Carruth   SmallString<4096> CheckFileBuffer;
1430b03c166aSChandler Carruth   StringRef CheckFileText = CanonicalizeFile(CheckFile, CheckFileBuffer);
143120247900SChandler Carruth 
143220247900SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
143320247900SChandler Carruth                             CheckFileText, CheckFile.getBufferIdentifier()),
143420247900SChandler Carruth                         SMLoc());
143520247900SChandler Carruth 
143626cccfe1SChris Lattner   std::vector<CheckString> CheckStrings;
1437726774cbSChandler Carruth   if (ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings))
1438ee3c74fbSChris Lattner     return 2;
1439ee3c74fbSChris Lattner 
1440ee3c74fbSChris Lattner   // Open the file to check and add it to SourceMgr.
144120247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
1442adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(InputFilename);
144320247900SChandler Carruth   if (std::error_code EC = InputFileOrErr.getError()) {
1444adf21f2aSRafael Espindola     errs() << "Could not open input file '" << InputFilename
1445adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
14468e1c6477SEli Bendersky     return 2;
1447ee3c74fbSChris Lattner   }
144820247900SChandler Carruth   MemoryBuffer &InputFile = *InputFileOrErr.get();
14492c3e5cdfSChris Lattner 
145020247900SChandler Carruth   if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
1451b692bed7SChris Lattner     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
14522bd4f8b6SXinliang David Li     DumpCommandLine(argc, argv);
14538e1c6477SEli Bendersky     return 2;
1454b692bed7SChris Lattner   }
1455b692bed7SChris Lattner 
145620247900SChandler Carruth   SmallString<4096> InputFileBuffer;
1457b03c166aSChandler Carruth   StringRef InputFileText = CanonicalizeFile(InputFile, InputFileBuffer);
14582c3e5cdfSChris Lattner 
1459e8f2fb20SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
1460e8f2fb20SChandler Carruth                             InputFileText, InputFile.getBufferIdentifier()),
1461e8f2fb20SChandler Carruth                         SMLoc());
1462ee3c74fbSChris Lattner 
146320247900SChandler Carruth   return CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
1464ee3c74fbSChris Lattner }
1465