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"
24*197194b6SRui 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,
1000a4c44bdSChris Lattner 
1014dabac20SChandler Carruth   /// Indicates the pattern only matches the end of file. This is used for
1024dabac20SChandler Carruth   /// trailing CHECK-NOTs.
103a908e7bdSPaul Robinson   CheckEOF,
1044dabac20SChandler Carruth 
1054dabac20SChandler Carruth   /// Marks when parsing found a -NOT check combined with another CHECK suffix.
106a908e7bdSPaul Robinson   CheckBadNot
10738820972SMatt Arsenault };
10838820972SMatt Arsenault }
109eba55822SJakob Stoklund Olesen 
11038820972SMatt Arsenault class Pattern {
11138820972SMatt Arsenault   SMLoc PatternLoc;
11291a1b2c9SMichael Liao 
1134dabac20SChandler Carruth   /// A fixed string to match as the pattern or empty if this pattern requires
1144dabac20SChandler Carruth   /// a regex match.
115221460e0SChris Lattner   StringRef FixedStr;
116b16ab0c4SChris Lattner 
1174dabac20SChandler Carruth   /// A regex string to match as the pattern or empty if this pattern requires
1184dabac20SChandler Carruth   /// a fixed string to match.
119b16ab0c4SChris Lattner   std::string RegExStr;
1208879e06dSChris Lattner 
1214dabac20SChandler Carruth   /// Entries in this vector map to uses of a variable in the pattern, e.g.
1224dabac20SChandler Carruth   /// "foo[[bar]]baz".  In this case, the RegExStr will contain "foobaz" and
1234dabac20SChandler Carruth   /// we'll get an entry in this vector that tells us to insert the value of
1244dabac20SChandler Carruth   /// bar at offset 3.
1258879e06dSChris Lattner   std::vector<std::pair<StringRef, unsigned>> VariableUses;
1268879e06dSChris Lattner 
1274dabac20SChandler Carruth   /// Maps definitions of variables to their parenthesized capture numbers.
1284dabac20SChandler Carruth   ///
1294dabac20SChandler Carruth   /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to
1304dabac20SChandler Carruth   /// 1.
131e8b8f1bcSEli Bendersky   std::map<StringRef, unsigned> VariableDefs;
1328879e06dSChris Lattner 
133d1e020f7SSaleem Abdulrasool   Check::CheckType CheckTy;
1343b40b445SChris Lattner 
1354dabac20SChandler Carruth   /// Contains the number of line this pattern is in.
136d1e020f7SSaleem Abdulrasool   unsigned LineNumber;
137d1e020f7SSaleem Abdulrasool 
138d1e020f7SSaleem Abdulrasool public:
139d1e020f7SSaleem Abdulrasool   explicit Pattern(Check::CheckType Ty) : CheckTy(Ty) {}
14074d50731SChris Lattner 
1414dabac20SChandler Carruth   /// Returns the location in source code.
1420b707eb8SMichael Liao   SMLoc getLoc() const { return PatternLoc; }
1430b707eb8SMichael Liao 
144e8f2fb20SChandler Carruth   bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
14513df4626SMatt Arsenault                     unsigned LineNumber);
1468879e06dSChris Lattner   size_t Match(StringRef Buffer, size_t &MatchLen,
1478879e06dSChris Lattner                StringMap<StringRef> &VariableTable) const;
148e0ef65abSDaniel Dunbar   void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
149e0ef65abSDaniel Dunbar                         const StringMap<StringRef> &VariableTable) const;
150e0ef65abSDaniel Dunbar 
151e8f2fb20SChandler Carruth   bool hasVariable() const {
152e8f2fb20SChandler Carruth     return !(VariableUses.empty() && VariableDefs.empty());
153e8f2fb20SChandler Carruth   }
154f8bd2e5bSStephen Lin 
15538820972SMatt Arsenault   Check::CheckType getCheckTy() const { return CheckTy; }
15691a1b2c9SMichael Liao 
157b16ab0c4SChris Lattner private:
158e8b8f1bcSEli Bendersky   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
159e8b8f1bcSEli Bendersky   void AddBackrefToRegEx(unsigned BackrefNum);
160e8f2fb20SChandler Carruth   unsigned
161e8f2fb20SChandler Carruth   ComputeMatchDistance(StringRef Buffer,
162fd29d886SDaniel Dunbar                        const StringMap<StringRef> &VariableTable) const;
16392987fb3SAlexander Kornienko   bool EvaluateExpression(StringRef Expr, std::string &Value) const;
16481e5cd9eSAdrian Prantl   size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
1653b40b445SChris Lattner };
1663b40b445SChris Lattner 
1674dabac20SChandler Carruth /// Parses the given string into the Pattern.
1684dabac20SChandler Carruth ///
1694dabac20SChandler Carruth /// \p Prefix provides which prefix is being matched, \p SM provides the
1704dabac20SChandler Carruth /// SourceMgr used for error reports, and \p LineNumber is the line number in
1714dabac20SChandler Carruth /// the input file from which the pattern string was read. Returns true in
1724dabac20SChandler Carruth /// case of an error, false otherwise.
173e8f2fb20SChandler Carruth bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
174e8f2fb20SChandler Carruth                            SourceMgr &SM, unsigned LineNumber) {
17585913ccaSJames Y Knight   bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot;
17685913ccaSJames Y Knight 
17792987fb3SAlexander Kornienko   this->LineNumber = LineNumber;
1780a4c44bdSChris Lattner   PatternLoc = SMLoc::getFromPointer(PatternStr.data());
1790a4c44bdSChris Lattner 
1801714676aSTom de Vries   if (!(NoCanonicalizeWhiteSpace && MatchFullLines))
18174d50731SChris Lattner     // Ignore trailing whitespace.
18274d50731SChris Lattner     while (!PatternStr.empty() &&
18374d50731SChris Lattner            (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
18474d50731SChris Lattner       PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
18574d50731SChris Lattner 
18674d50731SChris Lattner   // Check that there is something on the line.
18774d50731SChris Lattner   if (PatternStr.empty()) {
18803b80a40SChris Lattner     SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
189e8f2fb20SChandler Carruth                     "found empty check string with prefix '" + Prefix + ":'");
19074d50731SChris Lattner     return true;
19174d50731SChris Lattner   }
19274d50731SChris Lattner 
193221460e0SChris Lattner   // Check to see if this is a fixed string, or if it has regex pieces.
19485913ccaSJames Y Knight   if (!MatchFullLinesHere &&
19585913ccaSJames Y Knight       (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
19685913ccaSJames Y Knight                                  PatternStr.find("[[") == StringRef::npos))) {
197221460e0SChris Lattner     FixedStr = PatternStr;
198221460e0SChris Lattner     return false;
199221460e0SChris Lattner   }
200221460e0SChris Lattner 
20185913ccaSJames Y Knight   if (MatchFullLinesHere) {
20285913ccaSJames Y Knight     RegExStr += '^';
20385913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
20485913ccaSJames Y Knight       RegExStr += " *";
20585913ccaSJames Y Knight   }
20685913ccaSJames Y Knight 
2078879e06dSChris Lattner   // Paren value #0 is for the fully matched string.  Any new parenthesized
20853e0679dSChris Lattner   // values add from there.
2098879e06dSChris Lattner   unsigned CurParen = 1;
2108879e06dSChris Lattner 
211b16ab0c4SChris Lattner   // Otherwise, there is at least one regex piece.  Build up the regex pattern
212b16ab0c4SChris Lattner   // by escaping scary characters in fixed strings, building up one big regex.
213f08d2db9SChris Lattner   while (!PatternStr.empty()) {
2148879e06dSChris Lattner     // RegEx matches.
21553e0679dSChris Lattner     if (PatternStr.startswith("{{")) {
21643d50d4aSEli Bendersky       // This is the start of a regex match.  Scan for the }}.
217f08d2db9SChris Lattner       size_t End = PatternStr.find("}}");
218f08d2db9SChris Lattner       if (End == StringRef::npos) {
219f08d2db9SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
22003b80a40SChris Lattner                         SourceMgr::DK_Error,
22103b80a40SChris Lattner                         "found start of regex string with no end '}}'");
222f08d2db9SChris Lattner         return true;
223f08d2db9SChris Lattner       }
224f08d2db9SChris Lattner 
225e53c95f1SChris Lattner       // Enclose {{}} patterns in parens just like [[]] even though we're not
226e53c95f1SChris Lattner       // capturing the result for any purpose.  This is required in case the
227e53c95f1SChris Lattner       // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
228e53c95f1SChris Lattner       // want this to turn into: "abc(x|z)def" not "abcx|zdef".
229e53c95f1SChris Lattner       RegExStr += '(';
230e53c95f1SChris Lattner       ++CurParen;
231e53c95f1SChris Lattner 
2328879e06dSChris Lattner       if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
2338879e06dSChris Lattner         return true;
234e53c95f1SChris Lattner       RegExStr += ')';
23553e0679dSChris Lattner 
2368879e06dSChris Lattner       PatternStr = PatternStr.substr(End + 2);
2378879e06dSChris Lattner       continue;
2388879e06dSChris Lattner     }
2398879e06dSChris Lattner 
2408879e06dSChris Lattner     // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
2418879e06dSChris Lattner     // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
2428879e06dSChris Lattner     // second form is [[foo]] which is a reference to foo.  The variable name
24357cb733bSDaniel Dunbar     // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
2448879e06dSChris Lattner     // it.  This is to catch some common errors.
24553e0679dSChris Lattner     if (PatternStr.startswith("[[")) {
246061d2baaSEli Bendersky       // Find the closing bracket pair ending the match.  End is going to be an
247061d2baaSEli Bendersky       // offset relative to the beginning of the match string.
24881e5cd9eSAdrian Prantl       size_t End = FindRegexVarEnd(PatternStr.substr(2), SM);
249061d2baaSEli Bendersky 
2508879e06dSChris Lattner       if (End == StringRef::npos) {
2518879e06dSChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
25203b80a40SChris Lattner                         SourceMgr::DK_Error,
25303b80a40SChris Lattner                         "invalid named regex reference, no ]] found");
254f08d2db9SChris Lattner         return true;
255f08d2db9SChris Lattner       }
256f08d2db9SChris Lattner 
257061d2baaSEli Bendersky       StringRef MatchStr = PatternStr.substr(2, End);
258061d2baaSEli Bendersky       PatternStr = PatternStr.substr(End + 4);
2598879e06dSChris Lattner 
2608879e06dSChris Lattner       // Get the regex name (e.g. "foo").
2618879e06dSChris Lattner       size_t NameEnd = MatchStr.find(':');
2628879e06dSChris Lattner       StringRef Name = MatchStr.substr(0, NameEnd);
2638879e06dSChris Lattner 
2648879e06dSChris Lattner       if (Name.empty()) {
26503b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
26603b80a40SChris Lattner                         "invalid name in named regex: empty name");
2678879e06dSChris Lattner         return true;
2688879e06dSChris Lattner       }
2698879e06dSChris Lattner 
27092987fb3SAlexander Kornienko       // Verify that the name/expression is well formed. FileCheck currently
27192987fb3SAlexander Kornienko       // supports @LINE, @LINE+number, @LINE-number expressions. The check here
27292987fb3SAlexander Kornienko       // is relaxed, more strict check is performed in \c EvaluateExpression.
27392987fb3SAlexander Kornienko       bool IsExpression = false;
27492987fb3SAlexander Kornienko       for (unsigned i = 0, e = Name.size(); i != e; ++i) {
275f55e72a5SArtem Belevich         if (i == 0) {
276f55e72a5SArtem Belevich           if (Name[i] == '$')  // Global vars start with '$'
277f55e72a5SArtem Belevich             continue;
278f55e72a5SArtem Belevich           if (Name[i] == '@') {
27992987fb3SAlexander Kornienko             if (NameEnd != StringRef::npos) {
28092987fb3SAlexander Kornienko               SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
28192987fb3SAlexander Kornienko                               SourceMgr::DK_Error,
28292987fb3SAlexander Kornienko                               "invalid name in named regex definition");
28392987fb3SAlexander Kornienko               return true;
28492987fb3SAlexander Kornienko             }
28592987fb3SAlexander Kornienko             IsExpression = true;
28692987fb3SAlexander Kornienko             continue;
28792987fb3SAlexander Kornienko           }
288f55e72a5SArtem Belevich         }
28992987fb3SAlexander Kornienko         if (Name[i] != '_' && !isalnum(Name[i]) &&
29092987fb3SAlexander Kornienko             (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
2918879e06dSChris Lattner           SM.PrintMessage(SMLoc::getFromPointer(Name.data() + i),
29203b80a40SChris Lattner                           SourceMgr::DK_Error, "invalid name in named regex");
2938879e06dSChris Lattner           return true;
2948879e06dSChris Lattner         }
29592987fb3SAlexander Kornienko       }
2968879e06dSChris Lattner 
2978879e06dSChris Lattner       // Name can't start with a digit.
29883c74e9fSGuy Benyei       if (isdigit(static_cast<unsigned char>(Name[0]))) {
29903b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
30003b80a40SChris Lattner                         "invalid name in named regex");
3018879e06dSChris Lattner         return true;
3028879e06dSChris Lattner       }
3038879e06dSChris Lattner 
3048879e06dSChris Lattner       // Handle [[foo]].
3058879e06dSChris Lattner       if (NameEnd == StringRef::npos) {
306e8b8f1bcSEli Bendersky         // Handle variables that were defined earlier on the same line by
307e8b8f1bcSEli Bendersky         // emitting a backreference.
308e8b8f1bcSEli Bendersky         if (VariableDefs.find(Name) != VariableDefs.end()) {
309e8b8f1bcSEli Bendersky           unsigned VarParenNum = VariableDefs[Name];
310e8b8f1bcSEli Bendersky           if (VarParenNum < 1 || VarParenNum > 9) {
311e8b8f1bcSEli Bendersky             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
312e8b8f1bcSEli Bendersky                             SourceMgr::DK_Error,
313e8b8f1bcSEli Bendersky                             "Can't back-reference more than 9 variables");
314e8b8f1bcSEli Bendersky             return true;
315e8b8f1bcSEli Bendersky           }
316e8b8f1bcSEli Bendersky           AddBackrefToRegEx(VarParenNum);
317e8b8f1bcSEli Bendersky         } else {
3188879e06dSChris Lattner           VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
319e8b8f1bcSEli Bendersky         }
3208879e06dSChris Lattner         continue;
3218879e06dSChris Lattner       }
3228879e06dSChris Lattner 
3238879e06dSChris Lattner       // Handle [[foo:.*]].
324e8b8f1bcSEli Bendersky       VariableDefs[Name] = CurParen;
3258879e06dSChris Lattner       RegExStr += '(';
3268879e06dSChris Lattner       ++CurParen;
3278879e06dSChris Lattner 
3288879e06dSChris Lattner       if (AddRegExToRegEx(MatchStr.substr(NameEnd + 1), CurParen, SM))
3298879e06dSChris Lattner         return true;
3308879e06dSChris Lattner 
3318879e06dSChris Lattner       RegExStr += ')';
3328879e06dSChris Lattner     }
3338879e06dSChris Lattner 
3348879e06dSChris Lattner     // Handle fixed string matches.
3358879e06dSChris Lattner     // Find the end, which is the start of the next regex.
3368879e06dSChris Lattner     size_t FixedMatchEnd = PatternStr.find("{{");
3378879e06dSChris Lattner     FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
3386f4f77b7SHans Wennborg     RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
3398879e06dSChris Lattner     PatternStr = PatternStr.substr(FixedMatchEnd);
340f08d2db9SChris Lattner   }
341f08d2db9SChris Lattner 
34285913ccaSJames Y Knight   if (MatchFullLinesHere) {
34385913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
34485913ccaSJames Y Knight       RegExStr += " *";
34585913ccaSJames Y Knight     RegExStr += '$';
34685913ccaSJames Y Knight   }
34785913ccaSJames Y Knight 
34874d50731SChris Lattner   return false;
34974d50731SChris Lattner }
35074d50731SChris Lattner 
351e8f2fb20SChandler Carruth bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
352e8b8f1bcSEli Bendersky   Regex R(RS);
3538879e06dSChris Lattner   std::string Error;
3548879e06dSChris Lattner   if (!R.isValid(Error)) {
355e8b8f1bcSEli Bendersky     SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
35603b80a40SChris Lattner                     "invalid regex: " + Error);
3578879e06dSChris Lattner     return true;
3588879e06dSChris Lattner   }
3598879e06dSChris Lattner 
360e8b8f1bcSEli Bendersky   RegExStr += RS.str();
3618879e06dSChris Lattner   CurParen += R.getNumMatches();
3628879e06dSChris Lattner   return false;
3638879e06dSChris Lattner }
364b16ab0c4SChris Lattner 
365e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
366e8b8f1bcSEli Bendersky   assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
367e8f2fb20SChandler Carruth   std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
368e8b8f1bcSEli Bendersky   RegExStr += Backref;
369e8b8f1bcSEli Bendersky }
370e8b8f1bcSEli Bendersky 
3714dabac20SChandler Carruth /// Evaluates expression and stores the result to \p Value.
3724dabac20SChandler Carruth ///
3734dabac20SChandler Carruth /// Returns true on success and false when the expression has invalid syntax.
37492987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
37592987fb3SAlexander Kornienko   // The only supported expression is @LINE([\+-]\d+)?
37692987fb3SAlexander Kornienko   if (!Expr.startswith("@LINE"))
37792987fb3SAlexander Kornienko     return false;
37892987fb3SAlexander Kornienko   Expr = Expr.substr(StringRef("@LINE").size());
37992987fb3SAlexander Kornienko   int Offset = 0;
38092987fb3SAlexander Kornienko   if (!Expr.empty()) {
38192987fb3SAlexander Kornienko     if (Expr[0] == '+')
38292987fb3SAlexander Kornienko       Expr = Expr.substr(1);
38392987fb3SAlexander Kornienko     else if (Expr[0] != '-')
38492987fb3SAlexander Kornienko       return false;
38592987fb3SAlexander Kornienko     if (Expr.getAsInteger(10, Offset))
38692987fb3SAlexander Kornienko       return false;
38792987fb3SAlexander Kornienko   }
38892987fb3SAlexander Kornienko   Value = llvm::itostr(LineNumber + Offset);
38992987fb3SAlexander Kornienko   return true;
39092987fb3SAlexander Kornienko }
39192987fb3SAlexander Kornienko 
3924dabac20SChandler Carruth /// Matches the pattern string against the input buffer \p Buffer
3934dabac20SChandler Carruth ///
3944dabac20SChandler Carruth /// This returns the position that is matched or npos if there is no match. If
3954dabac20SChandler Carruth /// there is a match, the size of the matched string is returned in \p
3964dabac20SChandler Carruth /// MatchLen.
3974dabac20SChandler Carruth ///
3984dabac20SChandler Carruth /// The \p VariableTable StringMap provides the current values of filecheck
3994dabac20SChandler Carruth /// variables and is updated if this match defines new values.
4008879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
4018879e06dSChris Lattner                       StringMap<StringRef> &VariableTable) const {
402eba55822SJakob Stoklund Olesen   // If this is the EOF pattern, match it immediately.
40338820972SMatt Arsenault   if (CheckTy == Check::CheckEOF) {
404eba55822SJakob Stoklund Olesen     MatchLen = 0;
405eba55822SJakob Stoklund Olesen     return Buffer.size();
406eba55822SJakob Stoklund Olesen   }
407eba55822SJakob Stoklund Olesen 
408221460e0SChris Lattner   // If this is a fixed string pattern, just match it now.
409221460e0SChris Lattner   if (!FixedStr.empty()) {
410221460e0SChris Lattner     MatchLen = FixedStr.size();
411221460e0SChris Lattner     return Buffer.find(FixedStr);
412221460e0SChris Lattner   }
413221460e0SChris Lattner 
414b16ab0c4SChris Lattner   // Regex match.
4158879e06dSChris Lattner 
4168879e06dSChris Lattner   // If there are variable uses, we need to create a temporary string with the
4178879e06dSChris Lattner   // actual value.
4188879e06dSChris Lattner   StringRef RegExToMatch = RegExStr;
4198879e06dSChris Lattner   std::string TmpStr;
4208879e06dSChris Lattner   if (!VariableUses.empty()) {
4218879e06dSChris Lattner     TmpStr = RegExStr;
4228879e06dSChris Lattner 
4238879e06dSChris Lattner     unsigned InsertOffset = 0;
4248f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
42592987fb3SAlexander Kornienko       std::string Value;
42692987fb3SAlexander Kornienko 
4278f870499SBenjamin Kramer       if (VariableUse.first[0] == '@') {
4288f870499SBenjamin Kramer         if (!EvaluateExpression(VariableUse.first, Value))
42992987fb3SAlexander Kornienko           return StringRef::npos;
43092987fb3SAlexander Kornienko       } else {
431e0ef65abSDaniel Dunbar         StringMap<StringRef>::iterator it =
4328f870499SBenjamin Kramer             VariableTable.find(VariableUse.first);
433e0ef65abSDaniel Dunbar         // If the variable is undefined, return an error.
434e0ef65abSDaniel Dunbar         if (it == VariableTable.end())
435e0ef65abSDaniel Dunbar           return StringRef::npos;
436e0ef65abSDaniel Dunbar 
4376f4f77b7SHans Wennborg         // Look up the value and escape it so that we can put it into the regex.
4386f4f77b7SHans Wennborg         Value += Regex::escape(it->second);
43992987fb3SAlexander Kornienko       }
4408879e06dSChris Lattner 
4418879e06dSChris Lattner       // Plop it into the regex at the adjusted offset.
4428f870499SBenjamin Kramer       TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset,
4438879e06dSChris Lattner                     Value.begin(), Value.end());
4448879e06dSChris Lattner       InsertOffset += Value.size();
4458879e06dSChris Lattner     }
4468879e06dSChris Lattner 
4478879e06dSChris Lattner     // Match the newly constructed regex.
4488879e06dSChris Lattner     RegExToMatch = TmpStr;
4498879e06dSChris Lattner   }
4508879e06dSChris Lattner 
451b16ab0c4SChris Lattner   SmallVector<StringRef, 4> MatchInfo;
4528879e06dSChris Lattner   if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
453f08d2db9SChris Lattner     return StringRef::npos;
454b16ab0c4SChris Lattner 
455b16ab0c4SChris Lattner   // Successful regex match.
456b16ab0c4SChris Lattner   assert(!MatchInfo.empty() && "Didn't get any match");
457b16ab0c4SChris Lattner   StringRef FullMatch = MatchInfo[0];
458b16ab0c4SChris Lattner 
4598879e06dSChris Lattner   // If this defines any variables, remember their values.
4608f870499SBenjamin Kramer   for (const auto &VariableDef : VariableDefs) {
4618f870499SBenjamin Kramer     assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
4628f870499SBenjamin Kramer     VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
4630a4c44bdSChris Lattner   }
4640a4c44bdSChris Lattner 
465b16ab0c4SChris Lattner   MatchLen = FullMatch.size();
466b16ab0c4SChris Lattner   return FullMatch.data() - Buffer.data();
467f08d2db9SChris Lattner }
468f08d2db9SChris Lattner 
4694dabac20SChandler Carruth 
4704dabac20SChandler Carruth /// Computes an arbitrary estimate for the quality of matching this pattern at
4714dabac20SChandler Carruth /// the start of \p Buffer; a distance of zero should correspond to a perfect
4724dabac20SChandler Carruth /// match.
473e8f2fb20SChandler Carruth unsigned
474e8f2fb20SChandler Carruth Pattern::ComputeMatchDistance(StringRef Buffer,
475fd29d886SDaniel Dunbar                               const StringMap<StringRef> &VariableTable) const {
476fd29d886SDaniel Dunbar   // Just compute the number of matching characters. For regular expressions, we
477fd29d886SDaniel Dunbar   // just compare against the regex itself and hope for the best.
478fd29d886SDaniel Dunbar   //
479fd29d886SDaniel Dunbar   // FIXME: One easy improvement here is have the regex lib generate a single
480fd29d886SDaniel Dunbar   // example regular expression which matches, and use that as the example
481fd29d886SDaniel Dunbar   // string.
482fd29d886SDaniel Dunbar   StringRef ExampleString(FixedStr);
483fd29d886SDaniel Dunbar   if (ExampleString.empty())
484fd29d886SDaniel Dunbar     ExampleString = RegExStr;
485fd29d886SDaniel Dunbar 
486e9aa36c8SDaniel Dunbar   // Only compare up to the first line in the buffer, or the string size.
487e9aa36c8SDaniel Dunbar   StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
488e9aa36c8SDaniel Dunbar   BufferPrefix = BufferPrefix.split('\n').first;
489e9aa36c8SDaniel Dunbar   return BufferPrefix.edit_distance(ExampleString);
490fd29d886SDaniel Dunbar }
491fd29d886SDaniel Dunbar 
4924dabac20SChandler Carruth /// Prints additional information about a failure to match involving this
4934dabac20SChandler Carruth /// pattern.
494e8f2fb20SChandler Carruth void Pattern::PrintFailureInfo(
495e8f2fb20SChandler Carruth     const SourceMgr &SM, StringRef Buffer,
496e0ef65abSDaniel Dunbar     const StringMap<StringRef> &VariableTable) const {
497e0ef65abSDaniel Dunbar   // If this was a regular expression using variables, print the current
498e0ef65abSDaniel Dunbar   // variable values.
499e0ef65abSDaniel Dunbar   if (!VariableUses.empty()) {
5008f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
501e69170a1SAlp Toker       SmallString<256> Msg;
502e69170a1SAlp Toker       raw_svector_ostream OS(Msg);
5038f870499SBenjamin Kramer       StringRef Var = VariableUse.first;
50492987fb3SAlexander Kornienko       if (Var[0] == '@') {
50592987fb3SAlexander Kornienko         std::string Value;
50692987fb3SAlexander Kornienko         if (EvaluateExpression(Var, Value)) {
50792987fb3SAlexander Kornienko           OS << "with expression \"";
50892987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\" equal to \"";
50992987fb3SAlexander Kornienko           OS.write_escaped(Value) << "\"";
51092987fb3SAlexander Kornienko         } else {
51192987fb3SAlexander Kornienko           OS << "uses incorrect expression \"";
51292987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
51392987fb3SAlexander Kornienko         }
51492987fb3SAlexander Kornienko       } else {
51592987fb3SAlexander Kornienko         StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
516e0ef65abSDaniel Dunbar 
517e0ef65abSDaniel Dunbar         // Check for undefined variable references.
518e0ef65abSDaniel Dunbar         if (it == VariableTable.end()) {
519e0ef65abSDaniel Dunbar           OS << "uses undefined variable \"";
52092987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
521e0ef65abSDaniel Dunbar         } else {
522e0ef65abSDaniel Dunbar           OS << "with variable \"";
523e0ef65abSDaniel Dunbar           OS.write_escaped(Var) << "\" equal to \"";
524e0ef65abSDaniel Dunbar           OS.write_escaped(it->second) << "\"";
525e0ef65abSDaniel Dunbar         }
52692987fb3SAlexander Kornienko       }
527e0ef65abSDaniel Dunbar 
52803b80a40SChris Lattner       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
52903b80a40SChris Lattner                       OS.str());
530e0ef65abSDaniel Dunbar     }
531e0ef65abSDaniel Dunbar   }
532fd29d886SDaniel Dunbar 
533fd29d886SDaniel Dunbar   // Attempt to find the closest/best fuzzy match.  Usually an error happens
534fd29d886SDaniel Dunbar   // because some string in the output didn't exactly match. In these cases, we
535fd29d886SDaniel Dunbar   // would like to show the user a best guess at what "should have" matched, to
536fd29d886SDaniel Dunbar   // save them having to actually check the input manually.
537fd29d886SDaniel Dunbar   size_t NumLinesForward = 0;
538fd29d886SDaniel Dunbar   size_t Best = StringRef::npos;
539fd29d886SDaniel Dunbar   double BestQuality = 0;
540fd29d886SDaniel Dunbar 
541fd29d886SDaniel Dunbar   // Use an arbitrary 4k limit on how far we will search.
5422bf486ebSDan Gohman   for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
543fd29d886SDaniel Dunbar     if (Buffer[i] == '\n')
544fd29d886SDaniel Dunbar       ++NumLinesForward;
545fd29d886SDaniel Dunbar 
546df22bbf7SDan Gohman     // Patterns have leading whitespace stripped, so skip whitespace when
547df22bbf7SDan Gohman     // looking for something which looks like a pattern.
548df22bbf7SDan Gohman     if (Buffer[i] == ' ' || Buffer[i] == '\t')
549df22bbf7SDan Gohman       continue;
550df22bbf7SDan Gohman 
551fd29d886SDaniel Dunbar     // Compute the "quality" of this match as an arbitrary combination of the
552fd29d886SDaniel Dunbar     // match distance and the number of lines skipped to get to this match.
553fd29d886SDaniel Dunbar     unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
554fd29d886SDaniel Dunbar     double Quality = Distance + (NumLinesForward / 100.);
555fd29d886SDaniel Dunbar 
556fd29d886SDaniel Dunbar     if (Quality < BestQuality || Best == StringRef::npos) {
557fd29d886SDaniel Dunbar       Best = i;
558fd29d886SDaniel Dunbar       BestQuality = Quality;
559fd29d886SDaniel Dunbar     }
560fd29d886SDaniel Dunbar   }
561fd29d886SDaniel Dunbar 
562fd29d886SDaniel Dunbar   // Print the "possible intended match here" line if we found something
563c069cc8eSDaniel Dunbar   // reasonable and not equal to what we showed in the "scanning from here"
564c069cc8eSDaniel Dunbar   // line.
565c069cc8eSDaniel Dunbar   if (Best && Best != StringRef::npos && BestQuality < 50) {
566fd29d886SDaniel Dunbar     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
56703b80a40SChris Lattner                     SourceMgr::DK_Note, "possible intended match here");
568fd29d886SDaniel Dunbar 
569fd29d886SDaniel Dunbar     // FIXME: If we wanted to be really friendly we would show why the match
570fd29d886SDaniel Dunbar     // failed, as it can be hard to spot simple one character differences.
571fd29d886SDaniel Dunbar   }
572e0ef65abSDaniel Dunbar }
57374d50731SChris Lattner 
5744dabac20SChandler Carruth /// Finds the closing sequence of a regex variable usage or definition.
5754dabac20SChandler Carruth ///
5764dabac20SChandler Carruth /// \p Str has to point in the beginning of the definition (right after the
5774dabac20SChandler Carruth /// opening sequence). Returns the offset of the closing sequence within Str,
5784dabac20SChandler Carruth /// or npos if it was not found.
57981e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
580061d2baaSEli Bendersky   // Offset keeps track of the current offset within the input Str
581061d2baaSEli Bendersky   size_t Offset = 0;
582061d2baaSEli Bendersky   // [...] Nesting depth
583061d2baaSEli Bendersky   size_t BracketDepth = 0;
584061d2baaSEli Bendersky 
585061d2baaSEli Bendersky   while (!Str.empty()) {
586061d2baaSEli Bendersky     if (Str.startswith("]]") && BracketDepth == 0)
587061d2baaSEli Bendersky       return Offset;
588061d2baaSEli Bendersky     if (Str[0] == '\\') {
589061d2baaSEli Bendersky       // Backslash escapes the next char within regexes, so skip them both.
590061d2baaSEli Bendersky       Str = Str.substr(2);
591061d2baaSEli Bendersky       Offset += 2;
592061d2baaSEli Bendersky     } else {
593061d2baaSEli Bendersky       switch (Str[0]) {
594061d2baaSEli Bendersky       default:
595061d2baaSEli Bendersky         break;
596061d2baaSEli Bendersky       case '[':
597061d2baaSEli Bendersky         BracketDepth++;
598061d2baaSEli Bendersky         break;
599061d2baaSEli Bendersky       case ']':
60081e5cd9eSAdrian Prantl         if (BracketDepth == 0) {
60181e5cd9eSAdrian Prantl           SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
60281e5cd9eSAdrian Prantl                           SourceMgr::DK_Error,
60381e5cd9eSAdrian Prantl                           "missing closing \"]\" for regex variable");
60481e5cd9eSAdrian Prantl           exit(1);
60581e5cd9eSAdrian Prantl         }
606061d2baaSEli Bendersky         BracketDepth--;
607061d2baaSEli Bendersky         break;
608061d2baaSEli Bendersky       }
609061d2baaSEli Bendersky       Str = Str.substr(1);
610061d2baaSEli Bendersky       Offset++;
611061d2baaSEli Bendersky     }
612061d2baaSEli Bendersky   }
613061d2baaSEli Bendersky 
614061d2baaSEli Bendersky   return StringRef::npos;
615061d2baaSEli Bendersky }
616061d2baaSEli Bendersky 
61774d50731SChris Lattner //===----------------------------------------------------------------------===//
61874d50731SChris Lattner // Check Strings.
61974d50731SChris Lattner //===----------------------------------------------------------------------===//
6203b40b445SChris Lattner 
6214dabac20SChandler Carruth /// A check that we found in the input file.
6223b40b445SChris Lattner struct CheckString {
6234dabac20SChandler Carruth   /// The pattern to match.
6243b40b445SChris Lattner   Pattern Pat;
62526cccfe1SChris Lattner 
6264dabac20SChandler Carruth   /// Which prefix name this check matched.
62713df4626SMatt Arsenault   StringRef Prefix;
62813df4626SMatt Arsenault 
6294dabac20SChandler Carruth   /// The location in the match file that the check string was specified.
63026cccfe1SChris Lattner   SMLoc Loc;
63126cccfe1SChris Lattner 
6324dabac20SChandler Carruth   /// All of the strings that are disallowed from occurring between this match
6334dabac20SChandler Carruth   /// string and the previous one (or start of file).
63491a1b2c9SMichael Liao   std::vector<Pattern> DagNotStrings;
635236d2d5eSChris Lattner 
63685913ccaSJames Y Knight   CheckString(const Pattern &P, StringRef S, SMLoc L)
63785913ccaSJames Y Knight       : Pat(P), Prefix(S), Loc(L) {}
638dcc7d48dSMichael Liao 
639e93a3a08SStephen Lin   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
640f8bd2e5bSStephen Lin                size_t &MatchLen, StringMap<StringRef> &VariableTable) const;
641dcc7d48dSMichael Liao 
642dcc7d48dSMichael Liao   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
64301ac1707SDuncan P. N. Exon Smith   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
644dcc7d48dSMichael Liao   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
64591a1b2c9SMichael Liao                 const std::vector<const Pattern *> &NotStrings,
64691a1b2c9SMichael Liao                 StringMap<StringRef> &VariableTable) const;
64791a1b2c9SMichael Liao   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
64891a1b2c9SMichael Liao                   std::vector<const Pattern *> &NotStrings,
649dcc7d48dSMichael Liao                   StringMap<StringRef> &VariableTable) const;
65026cccfe1SChris Lattner };
65126cccfe1SChris Lattner 
65220247900SChandler Carruth /// Canonicalize whitespaces in the file. Line endings are replaced with
65320247900SChandler Carruth /// UNIX-style '\n'.
654b03c166aSChandler Carruth static StringRef CanonicalizeFile(MemoryBuffer &MB,
65520247900SChandler Carruth                                   SmallVectorImpl<char> &OutputBuffer) {
65620247900SChandler Carruth   OutputBuffer.reserve(MB.getBufferSize());
657a2f8fc5aSChris Lattner 
65820247900SChandler Carruth   for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
659a2f8fc5aSChris Lattner        Ptr != End; ++Ptr) {
660fd781bf0SNAKAMURA Takumi     // Eliminate trailing dosish \r.
661fd781bf0SNAKAMURA Takumi     if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
662fd781bf0SNAKAMURA Takumi       continue;
663fd781bf0SNAKAMURA Takumi     }
664fd781bf0SNAKAMURA Takumi 
6655ea04c38SGuy Benyei     // If current char is not a horizontal whitespace or if horizontal
6665ea04c38SGuy Benyei     // whitespace canonicalization is disabled, dump it to output as is.
667b03c166aSChandler Carruth     if (NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
66820247900SChandler Carruth       OutputBuffer.push_back(*Ptr);
669a2f8fc5aSChris Lattner       continue;
670a2f8fc5aSChris Lattner     }
671a2f8fc5aSChris Lattner 
672a2f8fc5aSChris Lattner     // Otherwise, add one space and advance over neighboring space.
67320247900SChandler Carruth     OutputBuffer.push_back(' ');
674e8f2fb20SChandler Carruth     while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
675a2f8fc5aSChris Lattner       ++Ptr;
676a2f8fc5aSChris Lattner   }
677a2f8fc5aSChris Lattner 
67820247900SChandler Carruth   // Add a null byte and then return all but that byte.
67920247900SChandler Carruth   OutputBuffer.push_back('\0');
68020247900SChandler Carruth   return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
681a2f8fc5aSChris Lattner }
682a2f8fc5aSChris Lattner 
68338820972SMatt Arsenault static bool IsPartOfWord(char c) {
68438820972SMatt Arsenault   return (isalnum(c) || c == '-' || c == '_');
68538820972SMatt Arsenault }
68638820972SMatt Arsenault 
68713df4626SMatt Arsenault // Get the size of the prefix extension.
68813df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) {
68913df4626SMatt Arsenault   switch (Ty) {
69013df4626SMatt Arsenault   case Check::CheckNone:
691a908e7bdSPaul Robinson   case Check::CheckBadNot:
69213df4626SMatt Arsenault     return 0;
69313df4626SMatt Arsenault 
69413df4626SMatt Arsenault   case Check::CheckPlain:
69513df4626SMatt Arsenault     return sizeof(":") - 1;
69613df4626SMatt Arsenault 
69713df4626SMatt Arsenault   case Check::CheckNext:
69813df4626SMatt Arsenault     return sizeof("-NEXT:") - 1;
69913df4626SMatt Arsenault 
70001ac1707SDuncan P. N. Exon Smith   case Check::CheckSame:
70101ac1707SDuncan P. N. Exon Smith     return sizeof("-SAME:") - 1;
70201ac1707SDuncan P. N. Exon Smith 
70313df4626SMatt Arsenault   case Check::CheckNot:
70413df4626SMatt Arsenault     return sizeof("-NOT:") - 1;
70513df4626SMatt Arsenault 
70613df4626SMatt Arsenault   case Check::CheckDAG:
70713df4626SMatt Arsenault     return sizeof("-DAG:") - 1;
70813df4626SMatt Arsenault 
70913df4626SMatt Arsenault   case Check::CheckLabel:
71013df4626SMatt Arsenault     return sizeof("-LABEL:") - 1;
71113df4626SMatt Arsenault 
71213df4626SMatt Arsenault   case Check::CheckEOF:
71313df4626SMatt Arsenault     llvm_unreachable("Should not be using EOF size");
71413df4626SMatt Arsenault   }
71513df4626SMatt Arsenault 
71613df4626SMatt Arsenault   llvm_unreachable("Bad check type");
71713df4626SMatt Arsenault }
71813df4626SMatt Arsenault 
71913df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
72083e63d96SGeorge Rimar   if (Buffer.size() <= Prefix.size())
72183e63d96SGeorge Rimar     return Check::CheckNone;
72283e63d96SGeorge Rimar 
723c4d2d471SMatt Arsenault   char NextChar = Buffer[Prefix.size()];
72438820972SMatt Arsenault 
72538820972SMatt Arsenault   // Verify that the : is present after the prefix.
72613df4626SMatt Arsenault   if (NextChar == ':')
72738820972SMatt Arsenault     return Check::CheckPlain;
72838820972SMatt Arsenault 
72913df4626SMatt Arsenault   if (NextChar != '-')
73038820972SMatt Arsenault     return Check::CheckNone;
73138820972SMatt Arsenault 
732c4d2d471SMatt Arsenault   StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
73313df4626SMatt Arsenault   if (Rest.startswith("NEXT:"))
73438820972SMatt Arsenault     return Check::CheckNext;
73538820972SMatt Arsenault 
73601ac1707SDuncan P. N. Exon Smith   if (Rest.startswith("SAME:"))
73701ac1707SDuncan P. N. Exon Smith     return Check::CheckSame;
73801ac1707SDuncan P. N. Exon Smith 
73913df4626SMatt Arsenault   if (Rest.startswith("NOT:"))
74038820972SMatt Arsenault     return Check::CheckNot;
74138820972SMatt Arsenault 
74213df4626SMatt Arsenault   if (Rest.startswith("DAG:"))
74338820972SMatt Arsenault     return Check::CheckDAG;
74438820972SMatt Arsenault 
74513df4626SMatt Arsenault   if (Rest.startswith("LABEL:"))
74638820972SMatt Arsenault     return Check::CheckLabel;
74713df4626SMatt Arsenault 
748a908e7bdSPaul Robinson   // You can't combine -NOT with another suffix.
749a908e7bdSPaul Robinson   if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
750a908e7bdSPaul Robinson       Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
751a908e7bdSPaul Robinson       Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:"))
752a908e7bdSPaul Robinson     return Check::CheckBadNot;
753a908e7bdSPaul Robinson 
75413df4626SMatt Arsenault   return Check::CheckNone;
75538820972SMatt Arsenault }
75638820972SMatt Arsenault 
75713df4626SMatt Arsenault // From the given position, find the next character after the word.
75813df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) {
75913df4626SMatt Arsenault   while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
76013df4626SMatt Arsenault     ++Loc;
76113df4626SMatt Arsenault   return Loc;
76213df4626SMatt Arsenault }
76313df4626SMatt Arsenault 
764726774cbSChandler Carruth /// Search the buffer for the first prefix in the prefix regular expression.
765726774cbSChandler Carruth ///
766726774cbSChandler Carruth /// This searches the buffer using the provided regular expression, however it
767726774cbSChandler Carruth /// enforces constraints beyond that:
768726774cbSChandler Carruth /// 1) The found prefix must not be a suffix of something that looks like
769726774cbSChandler Carruth ///    a valid prefix.
770726774cbSChandler Carruth /// 2) The found prefix must be followed by a valid check type suffix using \c
771726774cbSChandler Carruth ///    FindCheckType above.
772726774cbSChandler Carruth ///
773726774cbSChandler Carruth /// The first match of the regular expression to satisfy these two is returned,
774726774cbSChandler Carruth /// otherwise an empty StringRef is returned to indicate failure.
775726774cbSChandler Carruth ///
776726774cbSChandler Carruth /// If this routine returns a valid prefix, it will also shrink \p Buffer to
777726774cbSChandler Carruth /// start at the beginning of the returned prefix, increment \p LineNumber for
778726774cbSChandler Carruth /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
779726774cbSChandler Carruth /// check found by examining the suffix.
780726774cbSChandler Carruth ///
781726774cbSChandler Carruth /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
782726774cbSChandler Carruth /// is unspecified.
783726774cbSChandler Carruth static StringRef FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
78413df4626SMatt Arsenault                                          unsigned &LineNumber,
785726774cbSChandler Carruth                                          Check::CheckType &CheckTy) {
786726774cbSChandler Carruth   SmallVector<StringRef, 2> Matches;
787726774cbSChandler Carruth 
78813df4626SMatt Arsenault   while (!Buffer.empty()) {
789726774cbSChandler Carruth     // Find the first (longest) match using the RE.
790726774cbSChandler Carruth     if (!PrefixRE.match(Buffer, &Matches))
791726774cbSChandler Carruth       // No match at all, bail.
792726774cbSChandler Carruth       return StringRef();
793726774cbSChandler Carruth 
794726774cbSChandler Carruth     StringRef Prefix = Matches[0];
795726774cbSChandler Carruth     Matches.clear();
796726774cbSChandler Carruth 
797726774cbSChandler Carruth     assert(Prefix.data() >= Buffer.data() &&
798726774cbSChandler Carruth            Prefix.data() < Buffer.data() + Buffer.size() &&
799726774cbSChandler Carruth            "Prefix doesn't start inside of buffer!");
800726774cbSChandler Carruth     size_t Loc = Prefix.data() - Buffer.data();
801726774cbSChandler Carruth     StringRef Skipped = Buffer.substr(0, Loc);
802726774cbSChandler Carruth     Buffer = Buffer.drop_front(Loc);
803726774cbSChandler Carruth     LineNumber += Skipped.count('\n');
804726774cbSChandler Carruth 
805726774cbSChandler Carruth     // Check that the matched prefix isn't a suffix of some other check-like
806726774cbSChandler Carruth     // word.
807726774cbSChandler Carruth     // FIXME: This is a very ad-hoc check. it would be better handled in some
808726774cbSChandler Carruth     // other way. Among other things it seems hard to distinguish between
809726774cbSChandler Carruth     // intentional and unintentional uses of this feature.
810726774cbSChandler Carruth     if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
811726774cbSChandler Carruth       // Now extract the type.
812726774cbSChandler Carruth       CheckTy = FindCheckType(Buffer, Prefix);
813726774cbSChandler Carruth 
814726774cbSChandler Carruth       // If we've found a valid check type for this prefix, we're done.
815726774cbSChandler Carruth       if (CheckTy != Check::CheckNone)
81613df4626SMatt Arsenault         return Prefix;
81713df4626SMatt Arsenault     }
81813df4626SMatt Arsenault 
819726774cbSChandler Carruth     // If we didn't successfully find a prefix, we need to skip this invalid
820726774cbSChandler Carruth     // prefix and continue scanning. We directly skip the prefix that was
821726774cbSChandler Carruth     // matched and any additional parts of that check-like word.
822726774cbSChandler Carruth     Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
82313df4626SMatt Arsenault   }
82413df4626SMatt Arsenault 
825726774cbSChandler Carruth   // We ran out of buffer while skipping partial matches so give up.
82613df4626SMatt Arsenault   return StringRef();
82738820972SMatt Arsenault }
828ee3c74fbSChris Lattner 
8294dabac20SChandler Carruth /// Read the check file, which specifies the sequence of expected strings.
8304dabac20SChandler Carruth ///
8314dabac20SChandler Carruth /// The strings are added to the CheckStrings vector. Returns true in case of
8324dabac20SChandler Carruth /// an error, false otherwise.
833726774cbSChandler Carruth static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
83426cccfe1SChris Lattner                           std::vector<CheckString> &CheckStrings) {
83556ccdbbdSAlexander Kornienko   std::vector<Pattern> ImplicitNegativeChecks;
83656ccdbbdSAlexander Kornienko   for (const auto &PatternString : ImplicitCheckNot) {
83756ccdbbdSAlexander Kornienko     // Create a buffer with fake command line content in order to display the
83856ccdbbdSAlexander Kornienko     // command line option responsible for the specific implicit CHECK-NOT.
839ff43d69dSDavid Blaikie     std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str();
84056ccdbbdSAlexander Kornienko     std::string Suffix = "'";
8413560ff2cSRafael Espindola     std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
8423560ff2cSRafael Espindola         Prefix + PatternString + Suffix, "command line");
8433560ff2cSRafael Espindola 
84456ccdbbdSAlexander Kornienko     StringRef PatternInBuffer =
84556ccdbbdSAlexander Kornienko         CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
8461961f14cSDavid Blaikie     SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
84756ccdbbdSAlexander Kornienko 
84856ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot));
84956ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
85056ccdbbdSAlexander Kornienko                                                "IMPLICIT-CHECK", SM, 0);
85156ccdbbdSAlexander Kornienko   }
85256ccdbbdSAlexander Kornienko 
85356ccdbbdSAlexander Kornienko   std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
854236d2d5eSChris Lattner 
85543d50d4aSEli Bendersky   // LineNumber keeps track of the line on which CheckPrefix instances are
85643d50d4aSEli Bendersky   // found.
85792987fb3SAlexander Kornienko   unsigned LineNumber = 1;
85892987fb3SAlexander Kornienko 
859ee3c74fbSChris Lattner   while (1) {
86013df4626SMatt Arsenault     Check::CheckType CheckTy;
86113df4626SMatt Arsenault 
86213df4626SMatt Arsenault     // See if a prefix occurs in the memory buffer.
863726774cbSChandler Carruth     StringRef UsedPrefix = FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber,
864726774cbSChandler Carruth                                                    CheckTy);
86513df4626SMatt Arsenault     if (UsedPrefix.empty())
866ee3c74fbSChris Lattner       break;
867726774cbSChandler Carruth     assert(UsedPrefix.data() == Buffer.data() &&
868726774cbSChandler Carruth            "Failed to move Buffer's start forward, or pointed prefix outside "
869726774cbSChandler Carruth            "of the buffer!");
87092987fb3SAlexander Kornienko 
87113df4626SMatt Arsenault     // Location to use for error messages.
872726774cbSChandler Carruth     const char *UsedPrefixStart = UsedPrefix.data();
87392987fb3SAlexander Kornienko 
874726774cbSChandler Carruth     // Skip the buffer to the end.
87513df4626SMatt Arsenault     Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
87610f10cedSChris Lattner 
877a908e7bdSPaul Robinson     // Complain about useful-looking but unsupported suffixes.
878a908e7bdSPaul Robinson     if (CheckTy == Check::CheckBadNot) {
879e8f2fb20SChandler Carruth       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
880a908e7bdSPaul Robinson                       "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
881a908e7bdSPaul Robinson       return true;
882a908e7bdSPaul Robinson     }
883a908e7bdSPaul Robinson 
88438820972SMatt Arsenault     // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
885a26bc914STom de Vries     // leading whitespace.
8861714676aSTom de Vries     if (!(NoCanonicalizeWhiteSpace && MatchFullLines))
887236d2d5eSChris Lattner       Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
888ee3c74fbSChris Lattner 
889ee3c74fbSChris Lattner     // Scan ahead to the end of line.
890caa5fc0cSChris Lattner     size_t EOL = Buffer.find_first_of("\n\r");
891ee3c74fbSChris Lattner 
892838fb09aSDan Gohman     // Remember the location of the start of the pattern, for diagnostics.
893838fb09aSDan Gohman     SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
894838fb09aSDan Gohman 
89574d50731SChris Lattner     // Parse the pattern.
89638820972SMatt Arsenault     Pattern P(CheckTy);
89713df4626SMatt Arsenault     if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber))
898ee3c74fbSChris Lattner       return true;
899ee3c74fbSChris Lattner 
900f8bd2e5bSStephen Lin     // Verify that CHECK-LABEL lines do not define or use variables
90138820972SMatt Arsenault     if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
902e8f2fb20SChandler Carruth       SM.PrintMessage(
903e8f2fb20SChandler Carruth           SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
90413df4626SMatt Arsenault           "found '" + UsedPrefix + "-LABEL:'"
90513df4626SMatt Arsenault                                    " with variable definition or use");
906f8bd2e5bSStephen Lin       return true;
907f8bd2e5bSStephen Lin     }
908f8bd2e5bSStephen Lin 
909236d2d5eSChris Lattner     Buffer = Buffer.substr(EOL);
91074d50731SChris Lattner 
911da108b4eSChris Lattner     // Verify that CHECK-NEXT lines have at least one CHECK line before them.
91201ac1707SDuncan P. N. Exon Smith     if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
91301ac1707SDuncan P. N. Exon Smith         CheckStrings.empty()) {
91401ac1707SDuncan P. N. Exon Smith       StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
91513df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
91603b80a40SChris Lattner                       SourceMgr::DK_Error,
917e8f2fb20SChandler Carruth                       "found '" + UsedPrefix + "-" + Type +
918e8f2fb20SChandler Carruth                           "' without previous '" + UsedPrefix + ": line");
919da108b4eSChris Lattner       return true;
920da108b4eSChris Lattner     }
921da108b4eSChris Lattner 
92291a1b2c9SMichael Liao     // Handle CHECK-DAG/-NOT.
92338820972SMatt Arsenault     if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
92491a1b2c9SMichael Liao       DagNotMatches.push_back(P);
92574d50731SChris Lattner       continue;
92674d50731SChris Lattner     }
92774d50731SChris Lattner 
928ee3c74fbSChris Lattner     // Okay, add the string we captured to the output vector and move on.
92985913ccaSJames Y Knight     CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
93091a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
93156ccdbbdSAlexander Kornienko     DagNotMatches = ImplicitNegativeChecks;
932ee3c74fbSChris Lattner   }
933ee3c74fbSChris Lattner 
93413df4626SMatt Arsenault   // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
93513df4626SMatt Arsenault   // prefix as a filler for the error message.
93691a1b2c9SMichael Liao   if (!DagNotMatches.empty()) {
937f5e2fc47SBenjamin Kramer     CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(),
93885913ccaSJames Y Knight                               SMLoc::getFromPointer(Buffer.data()));
93991a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
940eba55822SJakob Stoklund Olesen   }
941eba55822SJakob Stoklund Olesen 
942ee3c74fbSChris Lattner   if (CheckStrings.empty()) {
94313df4626SMatt Arsenault     errs() << "error: no check strings found with prefix"
94413df4626SMatt Arsenault            << (CheckPrefixes.size() > 1 ? "es " : " ");
9453e3ef2f2SChris Bieneman     prefix_iterator I = CheckPrefixes.begin();
9463e3ef2f2SChris Bieneman     prefix_iterator E = CheckPrefixes.end();
9473e3ef2f2SChris Bieneman     if (I != E) {
9483e3ef2f2SChris Bieneman       errs() << "\'" << *I << ":'";
9493e3ef2f2SChris Bieneman       ++I;
95013df4626SMatt Arsenault     }
9513e3ef2f2SChris Bieneman     for (; I != E; ++I)
9523e3ef2f2SChris Bieneman       errs() << ", \'" << *I << ":'";
95313df4626SMatt Arsenault 
95413df4626SMatt Arsenault     errs() << '\n';
955ee3c74fbSChris Lattner     return true;
956ee3c74fbSChris Lattner   }
957ee3c74fbSChris Lattner 
958ee3c74fbSChris Lattner   return false;
959ee3c74fbSChris Lattner }
960ee3c74fbSChris Lattner 
961e8f2fb20SChandler Carruth static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
962e8f2fb20SChandler Carruth                              StringRef Buffer,
963e0ef65abSDaniel Dunbar                              StringMap<StringRef> &VariableTable) {
964da108b4eSChris Lattner   // Otherwise, we have an error, emit an error message.
96591a1b2c9SMichael Liao   SM.PrintMessage(Loc, SourceMgr::DK_Error,
96603b80a40SChris Lattner                   "expected string not found in input");
967da108b4eSChris Lattner 
968da108b4eSChris Lattner   // Print the "scanning from here" line.  If the current position is at the
969da108b4eSChris Lattner   // end of a line, advance to the start of the next line.
970caa5fc0cSChris Lattner   Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
971da108b4eSChris Lattner 
97203b80a40SChris Lattner   SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
97303b80a40SChris Lattner                   "scanning from here");
974e0ef65abSDaniel Dunbar 
975e0ef65abSDaniel Dunbar   // Allow the pattern to print additional information if desired.
97691a1b2c9SMichael Liao   Pat.PrintFailureInfo(SM, Buffer, VariableTable);
97791a1b2c9SMichael Liao }
97891a1b2c9SMichael Liao 
97991a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
98091a1b2c9SMichael Liao                              StringRef Buffer,
98191a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) {
98291a1b2c9SMichael Liao   PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
983da108b4eSChris Lattner }
984da108b4eSChris Lattner 
9854dabac20SChandler Carruth /// Count the number of newlines in the specified range.
986592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range,
987592fe880SRichard Smith                                         const char *&FirstNewLine) {
988da108b4eSChris Lattner   unsigned NumNewLines = 0;
98937183584SChris Lattner   while (1) {
990da108b4eSChris Lattner     // Scan for newline.
99137183584SChris Lattner     Range = Range.substr(Range.find_first_of("\n\r"));
992e8f2fb20SChandler Carruth     if (Range.empty())
993e8f2fb20SChandler Carruth       return NumNewLines;
994da108b4eSChris Lattner 
995da108b4eSChris Lattner     ++NumNewLines;
996da108b4eSChris Lattner 
997da108b4eSChris Lattner     // Handle \n\r and \r\n as a single newline.
998e8f2fb20SChandler Carruth     if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
99937183584SChris Lattner         (Range[0] != Range[1]))
100037183584SChris Lattner       Range = Range.substr(1);
100137183584SChris Lattner     Range = Range.substr(1);
1002592fe880SRichard Smith 
1003592fe880SRichard Smith     if (NumNewLines == 1)
1004592fe880SRichard Smith       FirstNewLine = Range.begin();
1005da108b4eSChris Lattner   }
1006da108b4eSChris Lattner }
1007da108b4eSChris Lattner 
10084dabac20SChandler Carruth /// Match check string and its "not strings" and/or "dag strings".
1009dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
1010e93a3a08SStephen Lin                           bool IsLabelScanMode, size_t &MatchLen,
1011dcc7d48dSMichael Liao                           StringMap<StringRef> &VariableTable) const {
101291a1b2c9SMichael Liao   size_t LastPos = 0;
101391a1b2c9SMichael Liao   std::vector<const Pattern *> NotStrings;
101491a1b2c9SMichael Liao 
1015e93a3a08SStephen Lin   // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1016e93a3a08SStephen Lin   // bounds; we have not processed variable definitions within the bounded block
1017e93a3a08SStephen Lin   // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1018e93a3a08SStephen Lin   // over the block again (including the last CHECK-LABEL) in normal mode.
1019e93a3a08SStephen Lin   if (!IsLabelScanMode) {
102091a1b2c9SMichael Liao     // Match "dag strings" (with mixed "not strings" if any).
102191a1b2c9SMichael Liao     LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable);
102291a1b2c9SMichael Liao     if (LastPos == StringRef::npos)
102391a1b2c9SMichael Liao       return StringRef::npos;
1024e93a3a08SStephen Lin   }
102591a1b2c9SMichael Liao 
102691a1b2c9SMichael Liao   // Match itself from the last position after matching CHECK-DAG.
102791a1b2c9SMichael Liao   StringRef MatchBuffer = Buffer.substr(LastPos);
102891a1b2c9SMichael Liao   size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
1029dcc7d48dSMichael Liao   if (MatchPos == StringRef::npos) {
103091a1b2c9SMichael Liao     PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
1031dcc7d48dSMichael Liao     return StringRef::npos;
1032dcc7d48dSMichael Liao   }
1033dcc7d48dSMichael Liao 
1034e93a3a08SStephen Lin   // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1035e93a3a08SStephen Lin   // or CHECK-NOT
1036e93a3a08SStephen Lin   if (!IsLabelScanMode) {
103791a1b2c9SMichael Liao     StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1038dcc7d48dSMichael Liao 
1039dcc7d48dSMichael Liao     // If this check is a "CHECK-NEXT", verify that the previous match was on
1040dcc7d48dSMichael Liao     // the previous line (i.e. that there is one newline between them).
1041dcc7d48dSMichael Liao     if (CheckNext(SM, SkippedRegion))
1042dcc7d48dSMichael Liao       return StringRef::npos;
1043dcc7d48dSMichael Liao 
104401ac1707SDuncan P. N. Exon Smith     // If this check is a "CHECK-SAME", verify that the previous match was on
104501ac1707SDuncan P. N. Exon Smith     // the same line (i.e. that there is no newline between them).
104601ac1707SDuncan P. N. Exon Smith     if (CheckSame(SM, SkippedRegion))
104701ac1707SDuncan P. N. Exon Smith       return StringRef::npos;
104801ac1707SDuncan P. N. Exon Smith 
1049dcc7d48dSMichael Liao     // If this match had "not strings", verify that they don't exist in the
1050dcc7d48dSMichael Liao     // skipped region.
105191a1b2c9SMichael Liao     if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
1052dcc7d48dSMichael Liao       return StringRef::npos;
1053f8bd2e5bSStephen Lin   }
1054dcc7d48dSMichael Liao 
10557dfb92b9SMehdi Amini   return LastPos + MatchPos;
1056dcc7d48dSMichael Liao }
1057dcc7d48dSMichael Liao 
10584dabac20SChandler Carruth /// Verify there is a single line in the given buffer.
1059dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
106085913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckNext)
1061dcc7d48dSMichael Liao     return false;
1062dcc7d48dSMichael Liao 
1063dcc7d48dSMichael Liao   // Count the number of newlines between the previous match and this one.
1064dcc7d48dSMichael Liao   assert(Buffer.data() !=
1065e8f2fb20SChandler Carruth              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
1066e8f2fb20SChandler Carruth                                     SMLoc::getFromPointer(Buffer.data())))
1067e8f2fb20SChandler Carruth                  ->getBufferStart() &&
1068dcc7d48dSMichael Liao          "CHECK-NEXT can't be the first check in a file");
1069dcc7d48dSMichael Liao 
107066f09ad0SCraig Topper   const char *FirstNewLine = nullptr;
1071592fe880SRichard Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1072dcc7d48dSMichael Liao 
1073dcc7d48dSMichael Liao   if (NumNewLines == 0) {
1074e8f2fb20SChandler Carruth     SM.PrintMessage(Loc, SourceMgr::DK_Error,
1075e8f2fb20SChandler Carruth                     Prefix + "-NEXT: is on the same line as previous match");
1076e8f2fb20SChandler Carruth     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1077e8f2fb20SChandler Carruth                     "'next' match was here");
1078dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1079dcc7d48dSMichael Liao                     "previous match ended here");
1080dcc7d48dSMichael Liao     return true;
1081dcc7d48dSMichael Liao   }
1082dcc7d48dSMichael Liao 
1083dcc7d48dSMichael Liao   if (NumNewLines != 1) {
1084e8f2fb20SChandler Carruth     SM.PrintMessage(Loc, SourceMgr::DK_Error,
1085e8f2fb20SChandler Carruth                     Prefix +
1086dcc7d48dSMichael Liao                         "-NEXT: is not on the line after the previous match");
1087e8f2fb20SChandler Carruth     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1088e8f2fb20SChandler Carruth                     "'next' match was here");
1089dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1090dcc7d48dSMichael Liao                     "previous match ended here");
1091592fe880SRichard Smith     SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
1092592fe880SRichard Smith                     "non-matching line after previous match is here");
1093dcc7d48dSMichael Liao     return true;
1094dcc7d48dSMichael Liao   }
1095dcc7d48dSMichael Liao 
1096dcc7d48dSMichael Liao   return false;
1097dcc7d48dSMichael Liao }
1098dcc7d48dSMichael Liao 
10994dabac20SChandler Carruth /// Verify there is no newline in the given buffer.
110001ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
110185913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckSame)
110201ac1707SDuncan P. N. Exon Smith     return false;
110301ac1707SDuncan P. N. Exon Smith 
110401ac1707SDuncan P. N. Exon Smith   // Count the number of newlines between the previous match and this one.
110501ac1707SDuncan P. N. Exon Smith   assert(Buffer.data() !=
110601ac1707SDuncan P. N. Exon Smith              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
110701ac1707SDuncan P. N. Exon Smith                                     SMLoc::getFromPointer(Buffer.data())))
110801ac1707SDuncan P. N. Exon Smith                  ->getBufferStart() &&
110901ac1707SDuncan P. N. Exon Smith          "CHECK-SAME can't be the first check in a file");
111001ac1707SDuncan P. N. Exon Smith 
111101ac1707SDuncan P. N. Exon Smith   const char *FirstNewLine = nullptr;
111201ac1707SDuncan P. N. Exon Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
111301ac1707SDuncan P. N. Exon Smith 
111401ac1707SDuncan P. N. Exon Smith   if (NumNewLines != 0) {
111501ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(Loc, SourceMgr::DK_Error,
111601ac1707SDuncan P. N. Exon Smith                     Prefix +
111701ac1707SDuncan P. N. Exon Smith                         "-SAME: is not on the same line as the previous match");
111801ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
111901ac1707SDuncan P. N. Exon Smith                     "'next' match was here");
112001ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
112101ac1707SDuncan P. N. Exon Smith                     "previous match ended here");
112201ac1707SDuncan P. N. Exon Smith     return true;
112301ac1707SDuncan P. N. Exon Smith   }
112401ac1707SDuncan P. N. Exon Smith 
112501ac1707SDuncan P. N. Exon Smith   return false;
112601ac1707SDuncan P. N. Exon Smith }
112701ac1707SDuncan P. N. Exon Smith 
11284dabac20SChandler Carruth /// Verify there's no "not strings" in the given buffer.
1129dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
113091a1b2c9SMichael Liao                            const std::vector<const Pattern *> &NotStrings,
1131dcc7d48dSMichael Liao                            StringMap<StringRef> &VariableTable) const {
11328f870499SBenjamin Kramer   for (const Pattern *Pat : NotStrings) {
113338820972SMatt Arsenault     assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
113491a1b2c9SMichael Liao 
1135dcc7d48dSMichael Liao     size_t MatchLen = 0;
113691a1b2c9SMichael Liao     size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
1137dcc7d48dSMichael Liao 
1138e8f2fb20SChandler Carruth     if (Pos == StringRef::npos)
1139e8f2fb20SChandler Carruth       continue;
1140dcc7d48dSMichael Liao 
1141dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos),
1142e8f2fb20SChandler Carruth                     SourceMgr::DK_Error, Prefix + "-NOT: string occurred!");
114391a1b2c9SMichael Liao     SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
114413df4626SMatt Arsenault                     Prefix + "-NOT: pattern specified here");
1145dcc7d48dSMichael Liao     return true;
1146dcc7d48dSMichael Liao   }
1147dcc7d48dSMichael Liao 
1148dcc7d48dSMichael Liao   return false;
1149dcc7d48dSMichael Liao }
1150dcc7d48dSMichael Liao 
11514dabac20SChandler Carruth /// Match "dag strings" and their mixed "not strings".
115291a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
115391a1b2c9SMichael Liao                              std::vector<const Pattern *> &NotStrings,
115491a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) const {
115591a1b2c9SMichael Liao   if (DagNotStrings.empty())
115691a1b2c9SMichael Liao     return 0;
115791a1b2c9SMichael Liao 
115891a1b2c9SMichael Liao   size_t LastPos = 0;
115991a1b2c9SMichael Liao   size_t StartPos = LastPos;
116091a1b2c9SMichael Liao 
11618f870499SBenjamin Kramer   for (const Pattern &Pat : DagNotStrings) {
116238820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG ||
116338820972SMatt Arsenault             Pat.getCheckTy() == Check::CheckNot) &&
116491a1b2c9SMichael Liao            "Invalid CHECK-DAG or CHECK-NOT!");
116591a1b2c9SMichael Liao 
116638820972SMatt Arsenault     if (Pat.getCheckTy() == Check::CheckNot) {
116791a1b2c9SMichael Liao       NotStrings.push_back(&Pat);
116891a1b2c9SMichael Liao       continue;
116991a1b2c9SMichael Liao     }
117091a1b2c9SMichael Liao 
117138820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
117291a1b2c9SMichael Liao 
117391a1b2c9SMichael Liao     size_t MatchLen = 0, MatchPos;
117491a1b2c9SMichael Liao 
117591a1b2c9SMichael Liao     // CHECK-DAG always matches from the start.
117691a1b2c9SMichael Liao     StringRef MatchBuffer = Buffer.substr(StartPos);
117791a1b2c9SMichael Liao     MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
117891a1b2c9SMichael Liao     // With a group of CHECK-DAGs, a single mismatching means the match on
117991a1b2c9SMichael Liao     // that group of CHECK-DAGs fails immediately.
118091a1b2c9SMichael Liao     if (MatchPos == StringRef::npos) {
118191a1b2c9SMichael Liao       PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
118291a1b2c9SMichael Liao       return StringRef::npos;
118391a1b2c9SMichael Liao     }
118491a1b2c9SMichael Liao     // Re-calc it as the offset relative to the start of the original string.
118591a1b2c9SMichael Liao     MatchPos += StartPos;
118691a1b2c9SMichael Liao 
118791a1b2c9SMichael Liao     if (!NotStrings.empty()) {
118891a1b2c9SMichael Liao       if (MatchPos < LastPos) {
118991a1b2c9SMichael Liao         // Reordered?
119091a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
119191a1b2c9SMichael Liao                         SourceMgr::DK_Error,
119213df4626SMatt Arsenault                         Prefix + "-DAG: found a match of CHECK-DAG"
119391a1b2c9SMichael Liao                                  " reordering across a CHECK-NOT");
119491a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
119591a1b2c9SMichael Liao                         SourceMgr::DK_Note,
119613df4626SMatt Arsenault                         Prefix + "-DAG: the farthest match of CHECK-DAG"
119791a1b2c9SMichael Liao                                  " is found here");
119891a1b2c9SMichael Liao         SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
119913df4626SMatt Arsenault                         Prefix + "-NOT: the crossed pattern specified"
120091a1b2c9SMichael Liao                                  " here");
120191a1b2c9SMichael Liao         SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
120213df4626SMatt Arsenault                         Prefix + "-DAG: the reordered pattern specified"
120391a1b2c9SMichael Liao                                  " here");
120491a1b2c9SMichael Liao         return StringRef::npos;
120591a1b2c9SMichael Liao       }
120691a1b2c9SMichael Liao       // All subsequent CHECK-DAGs should be matched from the farthest
120791a1b2c9SMichael Liao       // position of all precedent CHECK-DAGs (including this one.)
120891a1b2c9SMichael Liao       StartPos = LastPos;
120991a1b2c9SMichael Liao       // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
121091a1b2c9SMichael Liao       // CHECK-DAG, verify that there's no 'not' strings occurred in that
121191a1b2c9SMichael Liao       // region.
1212cf60ab31SBenjamin Kramer       StringRef SkippedRegion = Buffer.slice(LastPos, MatchPos);
1213cf708c32STim Northover       if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
121491a1b2c9SMichael Liao         return StringRef::npos;
121591a1b2c9SMichael Liao       // Clear "not strings".
121691a1b2c9SMichael Liao       NotStrings.clear();
121791a1b2c9SMichael Liao     }
121891a1b2c9SMichael Liao 
121991a1b2c9SMichael Liao     // Update the last position with CHECK-DAG matches.
122091a1b2c9SMichael Liao     LastPos = std::max(MatchPos + MatchLen, LastPos);
122191a1b2c9SMichael Liao   }
122291a1b2c9SMichael Liao 
122391a1b2c9SMichael Liao   return LastPos;
122491a1b2c9SMichael Liao }
122591a1b2c9SMichael Liao 
122613df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores.
122713df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) {
122813df4626SMatt Arsenault   Regex Validator("^[a-zA-Z0-9_-]*$");
122913df4626SMatt Arsenault   return Validator.match(CheckPrefix);
123013df4626SMatt Arsenault }
123113df4626SMatt Arsenault 
123213df4626SMatt Arsenault static bool ValidateCheckPrefixes() {
123313df4626SMatt Arsenault   StringSet<> PrefixSet;
123413df4626SMatt Arsenault 
12358f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
123624412b14SEli Bendersky     // Reject empty prefixes.
123724412b14SEli Bendersky     if (Prefix == "")
123824412b14SEli Bendersky       return false;
123924412b14SEli Bendersky 
12400356975cSDavid Blaikie     if (!PrefixSet.insert(Prefix).second)
124113df4626SMatt Arsenault       return false;
124213df4626SMatt Arsenault 
124313df4626SMatt Arsenault     if (!ValidateCheckPrefix(Prefix))
124413df4626SMatt Arsenault       return false;
124513df4626SMatt Arsenault   }
124613df4626SMatt Arsenault 
124713df4626SMatt Arsenault   return true;
124813df4626SMatt Arsenault }
124913df4626SMatt Arsenault 
1250726774cbSChandler Carruth // Combines the check prefixes into a single regex so that we can efficiently
1251726774cbSChandler Carruth // scan for any of the set.
1252726774cbSChandler Carruth //
1253726774cbSChandler Carruth // The semantics are that the longest-match wins which matches our regex
1254726774cbSChandler Carruth // library.
1255726774cbSChandler Carruth static Regex buildCheckPrefixRegex() {
125613df4626SMatt Arsenault   // I don't think there's a way to specify an initial value for cl::list,
125713df4626SMatt Arsenault   // so if nothing was specified, add the default
125813df4626SMatt Arsenault   if (CheckPrefixes.empty())
125913df4626SMatt Arsenault     CheckPrefixes.push_back("CHECK");
1260726774cbSChandler Carruth 
1261726774cbSChandler Carruth   // We already validated the contents of CheckPrefixes so just concatenate
1262726774cbSChandler Carruth   // them as alternatives.
1263726774cbSChandler Carruth   SmallString<32> PrefixRegexStr;
1264726774cbSChandler Carruth   for (StringRef Prefix : CheckPrefixes) {
1265726774cbSChandler Carruth     if (Prefix != CheckPrefixes.front())
1266726774cbSChandler Carruth       PrefixRegexStr.push_back('|');
1267726774cbSChandler Carruth 
1268726774cbSChandler Carruth     PrefixRegexStr.append(Prefix);
1269726774cbSChandler Carruth   }
1270726774cbSChandler Carruth 
1271726774cbSChandler Carruth   return Regex(PrefixRegexStr);
1272c2735158SRui Ueyama }
1273c2735158SRui Ueyama 
12742bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) {
12752bd4f8b6SXinliang David Li   errs() << "FileCheck command line: ";
12762bd4f8b6SXinliang David Li   for (int I = 0; I < argc; I++)
12772bd4f8b6SXinliang David Li     errs() << " " << argv[I];
12782bd4f8b6SXinliang David Li   errs() << "\n";
12792bd4f8b6SXinliang David Li }
12802bd4f8b6SXinliang David Li 
1281f55e72a5SArtem Belevich // Remove local variables from \p VariableTable. Global variables
1282f55e72a5SArtem Belevich // (start with '$') are preserved.
1283f55e72a5SArtem Belevich static void ClearLocalVars(StringMap<StringRef> &VariableTable) {
1284f55e72a5SArtem Belevich   SmallVector<StringRef, 16> LocalVars;
1285f55e72a5SArtem Belevich   for (const auto &Var : VariableTable)
1286f55e72a5SArtem Belevich     if (Var.first()[0] != '$')
1287f55e72a5SArtem Belevich       LocalVars.push_back(Var.first());
1288f55e72a5SArtem Belevich 
1289f55e72a5SArtem Belevich   for (const auto &Var : LocalVars)
1290f55e72a5SArtem Belevich     VariableTable.erase(Var);
1291f55e72a5SArtem Belevich }
1292f55e72a5SArtem Belevich 
129320247900SChandler Carruth /// Check the input to FileCheck provided in the \p Buffer against the \p
129420247900SChandler Carruth /// CheckStrings read from the check file.
129520247900SChandler Carruth ///
129620247900SChandler Carruth /// Returns false if the input fails to satisfy the checks.
129720247900SChandler Carruth bool CheckInput(SourceMgr &SM, StringRef Buffer,
129820247900SChandler Carruth                 ArrayRef<CheckString> CheckStrings) {
129920247900SChandler Carruth   bool ChecksFailed = false;
130020247900SChandler Carruth 
130120247900SChandler Carruth   /// VariableTable - This holds all the current filecheck variables.
130220247900SChandler Carruth   StringMap<StringRef> VariableTable;
130320247900SChandler Carruth 
130446e1fd61SAlexander Richardson   for (const auto& Def : GlobalDefines)
130546e1fd61SAlexander Richardson     VariableTable.insert(StringRef(Def).split('='));
130646e1fd61SAlexander Richardson 
130720247900SChandler Carruth   unsigned i = 0, j = 0, e = CheckStrings.size();
130820247900SChandler Carruth   while (true) {
130920247900SChandler Carruth     StringRef CheckRegion;
131020247900SChandler Carruth     if (j == e) {
131120247900SChandler Carruth       CheckRegion = Buffer;
131220247900SChandler Carruth     } else {
131320247900SChandler Carruth       const CheckString &CheckLabelStr = CheckStrings[j];
131420247900SChandler Carruth       if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
131520247900SChandler Carruth         ++j;
131620247900SChandler Carruth         continue;
131720247900SChandler Carruth       }
131820247900SChandler Carruth 
131920247900SChandler Carruth       // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
132020247900SChandler Carruth       size_t MatchLabelLen = 0;
1321e8f2fb20SChandler Carruth       size_t MatchLabelPos =
1322e8f2fb20SChandler Carruth           CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, VariableTable);
132320247900SChandler Carruth       if (MatchLabelPos == StringRef::npos)
132420247900SChandler Carruth         // Immediately bail of CHECK-LABEL fails, nothing else we can do.
132520247900SChandler Carruth         return false;
132620247900SChandler Carruth 
132720247900SChandler Carruth       CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
132820247900SChandler Carruth       Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
132920247900SChandler Carruth       ++j;
133020247900SChandler Carruth     }
133120247900SChandler Carruth 
1332f55e72a5SArtem Belevich     if (EnableVarScope)
1333f55e72a5SArtem Belevich       ClearLocalVars(VariableTable);
1334f55e72a5SArtem Belevich 
133520247900SChandler Carruth     for (; i != j; ++i) {
133620247900SChandler Carruth       const CheckString &CheckStr = CheckStrings[i];
133720247900SChandler Carruth 
133820247900SChandler Carruth       // Check each string within the scanned region, including a second check
133920247900SChandler Carruth       // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
134020247900SChandler Carruth       size_t MatchLen = 0;
1341e8f2fb20SChandler Carruth       size_t MatchPos =
1342e8f2fb20SChandler Carruth           CheckStr.Check(SM, CheckRegion, false, MatchLen, VariableTable);
134320247900SChandler Carruth 
134420247900SChandler Carruth       if (MatchPos == StringRef::npos) {
134520247900SChandler Carruth         ChecksFailed = true;
134620247900SChandler Carruth         i = j;
134720247900SChandler Carruth         break;
134820247900SChandler Carruth       }
134920247900SChandler Carruth 
135020247900SChandler Carruth       CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
135120247900SChandler Carruth     }
135220247900SChandler Carruth 
135320247900SChandler Carruth     if (j == e)
135420247900SChandler Carruth       break;
135520247900SChandler Carruth   }
135620247900SChandler Carruth 
135720247900SChandler Carruth   // Success if no checks failed.
135820247900SChandler Carruth   return !ChecksFailed;
135920247900SChandler Carruth }
136020247900SChandler Carruth 
1361ee3c74fbSChris Lattner int main(int argc, char **argv) {
1362*197194b6SRui Ueyama   InitLLVM X(argc, argv);
1363ee3c74fbSChris Lattner   cl::ParseCommandLineOptions(argc, argv);
1364ee3c74fbSChris Lattner 
136513df4626SMatt Arsenault   if (!ValidateCheckPrefixes()) {
136613df4626SMatt Arsenault     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
136713df4626SMatt Arsenault               "start with a letter and contain only alphanumeric characters, "
136813df4626SMatt Arsenault               "hyphens and underscores\n";
1369c2735158SRui Ueyama     return 2;
1370c2735158SRui Ueyama   }
1371c2735158SRui Ueyama 
1372726774cbSChandler Carruth   Regex PrefixRE = buildCheckPrefixRegex();
1373726774cbSChandler Carruth   std::string REError;
1374726774cbSChandler Carruth   if (!PrefixRE.isValid(REError)) {
1375726774cbSChandler Carruth     errs() << "Unable to combine check-prefix strings into a prefix regular "
1376726774cbSChandler Carruth               "expression! This is likely a bug in FileCheck's verification of "
1377726774cbSChandler Carruth               "the check-prefix strings. Regular expression parsing failed "
1378726774cbSChandler Carruth               "with the following error: "
1379726774cbSChandler Carruth            << REError << "\n";
1380726774cbSChandler Carruth     return 2;
1381726774cbSChandler Carruth   }
138213df4626SMatt Arsenault 
1383ee3c74fbSChris Lattner   SourceMgr SM;
1384ee3c74fbSChris Lattner 
1385ee3c74fbSChris Lattner   // Read the expected strings from the check file.
138620247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
138720247900SChandler Carruth       MemoryBuffer::getFileOrSTDIN(CheckFilename);
138820247900SChandler Carruth   if (std::error_code EC = CheckFileOrErr.getError()) {
138920247900SChandler Carruth     errs() << "Could not open check file '" << CheckFilename
139020247900SChandler Carruth            << "': " << EC.message() << '\n';
139120247900SChandler Carruth     return 2;
139220247900SChandler Carruth   }
139320247900SChandler Carruth   MemoryBuffer &CheckFile = *CheckFileOrErr.get();
139420247900SChandler Carruth 
139520247900SChandler Carruth   SmallString<4096> CheckFileBuffer;
1396b03c166aSChandler Carruth   StringRef CheckFileText = CanonicalizeFile(CheckFile, CheckFileBuffer);
139720247900SChandler Carruth 
139820247900SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
139920247900SChandler Carruth                             CheckFileText, CheckFile.getBufferIdentifier()),
140020247900SChandler Carruth                         SMLoc());
140120247900SChandler Carruth 
140226cccfe1SChris Lattner   std::vector<CheckString> CheckStrings;
1403726774cbSChandler Carruth   if (ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings))
1404ee3c74fbSChris Lattner     return 2;
1405ee3c74fbSChris Lattner 
1406ee3c74fbSChris Lattner   // Open the file to check and add it to SourceMgr.
140720247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
1408adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(InputFilename);
140920247900SChandler Carruth   if (std::error_code EC = InputFileOrErr.getError()) {
1410adf21f2aSRafael Espindola     errs() << "Could not open input file '" << InputFilename
1411adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
14128e1c6477SEli Bendersky     return 2;
1413ee3c74fbSChris Lattner   }
141420247900SChandler Carruth   MemoryBuffer &InputFile = *InputFileOrErr.get();
14152c3e5cdfSChris Lattner 
141620247900SChandler Carruth   if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
1417b692bed7SChris Lattner     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
14182bd4f8b6SXinliang David Li     DumpCommandLine(argc, argv);
14198e1c6477SEli Bendersky     return 2;
1420b692bed7SChris Lattner   }
1421b692bed7SChris Lattner 
142220247900SChandler Carruth   SmallString<4096> InputFileBuffer;
1423b03c166aSChandler Carruth   StringRef InputFileText = CanonicalizeFile(InputFile, InputFileBuffer);
14242c3e5cdfSChris Lattner 
1425e8f2fb20SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
1426e8f2fb20SChandler Carruth                             InputFileText, InputFile.getBufferIdentifier()),
1427e8f2fb20SChandler Carruth                         SMLoc());
1428ee3c74fbSChris Lattner 
142920247900SChandler Carruth   return CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
1430ee3c74fbSChris Lattner }
1431