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 //
13*b5ecceffSJames 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"
24ee3c74fbSChris Lattner #include "llvm/Support/MemoryBuffer.h"
25ee3c74fbSChris Lattner #include "llvm/Support/PrettyStackTrace.h"
26f08d2db9SChris Lattner #include "llvm/Support/Regex.h"
2791d19d8eSChandler Carruth #include "llvm/Support/Signals.h"
28ee3c74fbSChris Lattner #include "llvm/Support/SourceMgr.h"
29ee3c74fbSChris Lattner #include "llvm/Support/raw_ostream.h"
308879e06dSChris Lattner #include <algorithm>
31981af002SWill Dietz #include <cctype>
32e8b8f1bcSEli Bendersky #include <map>
33e8b8f1bcSEli Bendersky #include <string>
34a6e9c3e4SRafael Espindola #include <system_error>
35e8b8f1bcSEli Bendersky #include <vector>
36ee3c74fbSChris Lattner using namespace llvm;
37ee3c74fbSChris Lattner 
38ee3c74fbSChris Lattner static cl::opt<std::string>
39ee3c74fbSChris Lattner     CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
40ee3c74fbSChris Lattner 
41ee3c74fbSChris Lattner static cl::opt<std::string>
42ee3c74fbSChris Lattner     InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
43ee3c74fbSChris Lattner                   cl::init("-"), cl::value_desc("filename"));
44ee3c74fbSChris Lattner 
45e8f2fb20SChandler Carruth static cl::list<std::string> CheckPrefixes(
46e8f2fb20SChandler Carruth     "check-prefix",
47ee3c74fbSChris Lattner     cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
48fd557cb0SDaniel Sanders static cl::alias CheckPrefixesAlias(
49fd557cb0SDaniel Sanders     "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
50fd557cb0SDaniel Sanders     cl::NotHidden,
51fd557cb0SDaniel Sanders     cl::desc(
52fd557cb0SDaniel Sanders         "Alias for -check-prefix permitting multiple comma separated values"));
53ee3c74fbSChris Lattner 
54e8f2fb20SChandler Carruth static cl::opt<bool> NoCanonicalizeWhiteSpace(
55e8f2fb20SChandler Carruth     "strict-whitespace",
562c3e5cdfSChris Lattner     cl::desc("Do not treat all horizontal whitespace as equivalent"));
572c3e5cdfSChris Lattner 
5856ccdbbdSAlexander Kornienko static cl::list<std::string> ImplicitCheckNot(
5956ccdbbdSAlexander Kornienko     "implicit-check-not",
6056ccdbbdSAlexander Kornienko     cl::desc("Add an implicit negative check with this pattern to every\n"
6156ccdbbdSAlexander Kornienko              "positive check. This can be used to ensure that no instances of\n"
6256ccdbbdSAlexander Kornienko              "this pattern occur which are not matched by a positive pattern"),
6356ccdbbdSAlexander Kornienko     cl::value_desc("pattern"));
6456ccdbbdSAlexander Kornienko 
651b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput(
661b9f936fSJustin Bogner     "allow-empty", cl::init(false),
671b9f936fSJustin Bogner     cl::desc("Allow the input file to be empty. This is useful when making\n"
681b9f936fSJustin Bogner              "checks that some error message does not occur, for example."));
691b9f936fSJustin Bogner 
7085913ccaSJames Y Knight static cl::opt<bool> MatchFullLines(
7185913ccaSJames Y Knight     "match-full-lines", cl::init(false),
7285913ccaSJames Y Knight     cl::desc("Require all positive matches to cover an entire input line.\n"
7385913ccaSJames Y Knight              "Allows leading and trailing whitespace if --strict-whitespace\n"
7485913ccaSJames Y Knight              "is not also passed."));
7585913ccaSJames Y Knight 
76f55e72a5SArtem Belevich static cl::opt<bool> EnableVarScope(
77f55e72a5SArtem Belevich     "enable-var-scope", cl::init(false),
78f55e72a5SArtem Belevich     cl::desc("Enables scope for regex variables. Variables with names that\n"
79f55e72a5SArtem Belevich              "do not start with '$' will be reset at the beginning of\n"
80f55e72a5SArtem Belevich              "each CHECK-LABEL block."));
81f55e72a5SArtem Belevich 
8213df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator;
8313df4626SMatt Arsenault 
8474d50731SChris Lattner //===----------------------------------------------------------------------===//
8574d50731SChris Lattner // Pattern Handling Code.
8674d50731SChris Lattner //===----------------------------------------------------------------------===//
8774d50731SChris Lattner 
8838820972SMatt Arsenault namespace Check {
8938820972SMatt Arsenault enum CheckType {
9038820972SMatt Arsenault   CheckNone = 0,
9138820972SMatt Arsenault   CheckPlain,
9238820972SMatt Arsenault   CheckNext,
9301ac1707SDuncan P. N. Exon Smith   CheckSame,
9438820972SMatt Arsenault   CheckNot,
9538820972SMatt Arsenault   CheckDAG,
9638820972SMatt Arsenault   CheckLabel,
970a4c44bdSChris Lattner 
984dabac20SChandler Carruth   /// Indicates the pattern only matches the end of file. This is used for
994dabac20SChandler Carruth   /// trailing CHECK-NOTs.
100a908e7bdSPaul Robinson   CheckEOF,
1014dabac20SChandler Carruth 
1024dabac20SChandler Carruth   /// Marks when parsing found a -NOT check combined with another CHECK suffix.
103a908e7bdSPaul Robinson   CheckBadNot
10438820972SMatt Arsenault };
10538820972SMatt Arsenault }
106eba55822SJakob Stoklund Olesen 
10738820972SMatt Arsenault class Pattern {
10838820972SMatt Arsenault   SMLoc PatternLoc;
10991a1b2c9SMichael Liao 
1104dabac20SChandler Carruth   /// A fixed string to match as the pattern or empty if this pattern requires
1114dabac20SChandler Carruth   /// a regex match.
112221460e0SChris Lattner   StringRef FixedStr;
113b16ab0c4SChris Lattner 
1144dabac20SChandler Carruth   /// A regex string to match as the pattern or empty if this pattern requires
1154dabac20SChandler Carruth   /// a fixed string to match.
116b16ab0c4SChris Lattner   std::string RegExStr;
1178879e06dSChris Lattner 
1184dabac20SChandler Carruth   /// Entries in this vector map to uses of a variable in the pattern, e.g.
1194dabac20SChandler Carruth   /// "foo[[bar]]baz".  In this case, the RegExStr will contain "foobaz" and
1204dabac20SChandler Carruth   /// we'll get an entry in this vector that tells us to insert the value of
1214dabac20SChandler Carruth   /// bar at offset 3.
1228879e06dSChris Lattner   std::vector<std::pair<StringRef, unsigned>> VariableUses;
1238879e06dSChris Lattner 
1244dabac20SChandler Carruth   /// Maps definitions of variables to their parenthesized capture numbers.
1254dabac20SChandler Carruth   ///
1264dabac20SChandler Carruth   /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to
1274dabac20SChandler Carruth   /// 1.
128e8b8f1bcSEli Bendersky   std::map<StringRef, unsigned> VariableDefs;
1298879e06dSChris Lattner 
130d1e020f7SSaleem Abdulrasool   Check::CheckType CheckTy;
1313b40b445SChris Lattner 
1324dabac20SChandler Carruth   /// Contains the number of line this pattern is in.
133d1e020f7SSaleem Abdulrasool   unsigned LineNumber;
134d1e020f7SSaleem Abdulrasool 
135d1e020f7SSaleem Abdulrasool public:
136d1e020f7SSaleem Abdulrasool   explicit Pattern(Check::CheckType Ty) : CheckTy(Ty) {}
13774d50731SChris Lattner 
1384dabac20SChandler Carruth   /// Returns the location in source code.
1390b707eb8SMichael Liao   SMLoc getLoc() const { return PatternLoc; }
1400b707eb8SMichael Liao 
141e8f2fb20SChandler Carruth   bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
14213df4626SMatt Arsenault                     unsigned LineNumber);
1438879e06dSChris Lattner   size_t Match(StringRef Buffer, size_t &MatchLen,
1448879e06dSChris Lattner                StringMap<StringRef> &VariableTable) const;
145e0ef65abSDaniel Dunbar   void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
146e0ef65abSDaniel Dunbar                         const StringMap<StringRef> &VariableTable) const;
147e0ef65abSDaniel Dunbar 
148e8f2fb20SChandler Carruth   bool hasVariable() const {
149e8f2fb20SChandler Carruth     return !(VariableUses.empty() && VariableDefs.empty());
150e8f2fb20SChandler Carruth   }
151f8bd2e5bSStephen Lin 
15238820972SMatt Arsenault   Check::CheckType getCheckTy() const { return CheckTy; }
15391a1b2c9SMichael Liao 
154b16ab0c4SChris Lattner private:
155e8b8f1bcSEli Bendersky   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
156e8b8f1bcSEli Bendersky   void AddBackrefToRegEx(unsigned BackrefNum);
157e8f2fb20SChandler Carruth   unsigned
158e8f2fb20SChandler Carruth   ComputeMatchDistance(StringRef Buffer,
159fd29d886SDaniel Dunbar                        const StringMap<StringRef> &VariableTable) const;
16092987fb3SAlexander Kornienko   bool EvaluateExpression(StringRef Expr, std::string &Value) const;
16181e5cd9eSAdrian Prantl   size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
1623b40b445SChris Lattner };
1633b40b445SChris Lattner 
1644dabac20SChandler Carruth /// Parses the given string into the Pattern.
1654dabac20SChandler Carruth ///
1664dabac20SChandler Carruth /// \p Prefix provides which prefix is being matched, \p SM provides the
1674dabac20SChandler Carruth /// SourceMgr used for error reports, and \p LineNumber is the line number in
1684dabac20SChandler Carruth /// the input file from which the pattern string was read. Returns true in
1694dabac20SChandler Carruth /// case of an error, false otherwise.
170e8f2fb20SChandler Carruth bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
171e8f2fb20SChandler Carruth                            SourceMgr &SM, unsigned LineNumber) {
17285913ccaSJames Y Knight   bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot;
17385913ccaSJames Y Knight 
17492987fb3SAlexander Kornienko   this->LineNumber = LineNumber;
1750a4c44bdSChris Lattner   PatternLoc = SMLoc::getFromPointer(PatternStr.data());
1760a4c44bdSChris Lattner 
1771714676aSTom de Vries   if (!(NoCanonicalizeWhiteSpace && MatchFullLines))
17874d50731SChris Lattner     // Ignore trailing whitespace.
17974d50731SChris Lattner     while (!PatternStr.empty() &&
18074d50731SChris Lattner            (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
18174d50731SChris Lattner       PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
18274d50731SChris Lattner 
18374d50731SChris Lattner   // Check that there is something on the line.
18474d50731SChris Lattner   if (PatternStr.empty()) {
18503b80a40SChris Lattner     SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
186e8f2fb20SChandler Carruth                     "found empty check string with prefix '" + Prefix + ":'");
18774d50731SChris Lattner     return true;
18874d50731SChris Lattner   }
18974d50731SChris Lattner 
190221460e0SChris Lattner   // Check to see if this is a fixed string, or if it has regex pieces.
19185913ccaSJames Y Knight   if (!MatchFullLinesHere &&
19285913ccaSJames Y Knight       (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
19385913ccaSJames Y Knight                                  PatternStr.find("[[") == StringRef::npos))) {
194221460e0SChris Lattner     FixedStr = PatternStr;
195221460e0SChris Lattner     return false;
196221460e0SChris Lattner   }
197221460e0SChris Lattner 
19885913ccaSJames Y Knight   if (MatchFullLinesHere) {
19985913ccaSJames Y Knight     RegExStr += '^';
20085913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
20185913ccaSJames Y Knight       RegExStr += " *";
20285913ccaSJames Y Knight   }
20385913ccaSJames Y Knight 
2048879e06dSChris Lattner   // Paren value #0 is for the fully matched string.  Any new parenthesized
20553e0679dSChris Lattner   // values add from there.
2068879e06dSChris Lattner   unsigned CurParen = 1;
2078879e06dSChris Lattner 
208b16ab0c4SChris Lattner   // Otherwise, there is at least one regex piece.  Build up the regex pattern
209b16ab0c4SChris Lattner   // by escaping scary characters in fixed strings, building up one big regex.
210f08d2db9SChris Lattner   while (!PatternStr.empty()) {
2118879e06dSChris Lattner     // RegEx matches.
21253e0679dSChris Lattner     if (PatternStr.startswith("{{")) {
21343d50d4aSEli Bendersky       // This is the start of a regex match.  Scan for the }}.
214f08d2db9SChris Lattner       size_t End = PatternStr.find("}}");
215f08d2db9SChris Lattner       if (End == StringRef::npos) {
216f08d2db9SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
21703b80a40SChris Lattner                         SourceMgr::DK_Error,
21803b80a40SChris Lattner                         "found start of regex string with no end '}}'");
219f08d2db9SChris Lattner         return true;
220f08d2db9SChris Lattner       }
221f08d2db9SChris Lattner 
222e53c95f1SChris Lattner       // Enclose {{}} patterns in parens just like [[]] even though we're not
223e53c95f1SChris Lattner       // capturing the result for any purpose.  This is required in case the
224e53c95f1SChris Lattner       // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
225e53c95f1SChris Lattner       // want this to turn into: "abc(x|z)def" not "abcx|zdef".
226e53c95f1SChris Lattner       RegExStr += '(';
227e53c95f1SChris Lattner       ++CurParen;
228e53c95f1SChris Lattner 
2298879e06dSChris Lattner       if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
2308879e06dSChris Lattner         return true;
231e53c95f1SChris Lattner       RegExStr += ')';
23253e0679dSChris Lattner 
2338879e06dSChris Lattner       PatternStr = PatternStr.substr(End + 2);
2348879e06dSChris Lattner       continue;
2358879e06dSChris Lattner     }
2368879e06dSChris Lattner 
2378879e06dSChris Lattner     // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
2388879e06dSChris Lattner     // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
2398879e06dSChris Lattner     // second form is [[foo]] which is a reference to foo.  The variable name
24057cb733bSDaniel Dunbar     // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
2418879e06dSChris Lattner     // it.  This is to catch some common errors.
24253e0679dSChris Lattner     if (PatternStr.startswith("[[")) {
243061d2baaSEli Bendersky       // Find the closing bracket pair ending the match.  End is going to be an
244061d2baaSEli Bendersky       // offset relative to the beginning of the match string.
24581e5cd9eSAdrian Prantl       size_t End = FindRegexVarEnd(PatternStr.substr(2), SM);
246061d2baaSEli Bendersky 
2478879e06dSChris Lattner       if (End == StringRef::npos) {
2488879e06dSChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
24903b80a40SChris Lattner                         SourceMgr::DK_Error,
25003b80a40SChris Lattner                         "invalid named regex reference, no ]] found");
251f08d2db9SChris Lattner         return true;
252f08d2db9SChris Lattner       }
253f08d2db9SChris Lattner 
254061d2baaSEli Bendersky       StringRef MatchStr = PatternStr.substr(2, End);
255061d2baaSEli Bendersky       PatternStr = PatternStr.substr(End + 4);
2568879e06dSChris Lattner 
2578879e06dSChris Lattner       // Get the regex name (e.g. "foo").
2588879e06dSChris Lattner       size_t NameEnd = MatchStr.find(':');
2598879e06dSChris Lattner       StringRef Name = MatchStr.substr(0, NameEnd);
2608879e06dSChris Lattner 
2618879e06dSChris Lattner       if (Name.empty()) {
26203b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
26303b80a40SChris Lattner                         "invalid name in named regex: empty name");
2648879e06dSChris Lattner         return true;
2658879e06dSChris Lattner       }
2668879e06dSChris Lattner 
26792987fb3SAlexander Kornienko       // Verify that the name/expression is well formed. FileCheck currently
26892987fb3SAlexander Kornienko       // supports @LINE, @LINE+number, @LINE-number expressions. The check here
26992987fb3SAlexander Kornienko       // is relaxed, more strict check is performed in \c EvaluateExpression.
27092987fb3SAlexander Kornienko       bool IsExpression = false;
27192987fb3SAlexander Kornienko       for (unsigned i = 0, e = Name.size(); i != e; ++i) {
272f55e72a5SArtem Belevich         if (i == 0) {
273f55e72a5SArtem Belevich           if (Name[i] == '$')  // Global vars start with '$'
274f55e72a5SArtem Belevich             continue;
275f55e72a5SArtem Belevich           if (Name[i] == '@') {
27692987fb3SAlexander Kornienko             if (NameEnd != StringRef::npos) {
27792987fb3SAlexander Kornienko               SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
27892987fb3SAlexander Kornienko                               SourceMgr::DK_Error,
27992987fb3SAlexander Kornienko                               "invalid name in named regex definition");
28092987fb3SAlexander Kornienko               return true;
28192987fb3SAlexander Kornienko             }
28292987fb3SAlexander Kornienko             IsExpression = true;
28392987fb3SAlexander Kornienko             continue;
28492987fb3SAlexander Kornienko           }
285f55e72a5SArtem Belevich         }
28692987fb3SAlexander Kornienko         if (Name[i] != '_' && !isalnum(Name[i]) &&
28792987fb3SAlexander Kornienko             (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
2888879e06dSChris Lattner           SM.PrintMessage(SMLoc::getFromPointer(Name.data() + i),
28903b80a40SChris Lattner                           SourceMgr::DK_Error, "invalid name in named regex");
2908879e06dSChris Lattner           return true;
2918879e06dSChris Lattner         }
29292987fb3SAlexander Kornienko       }
2938879e06dSChris Lattner 
2948879e06dSChris Lattner       // Name can't start with a digit.
29583c74e9fSGuy Benyei       if (isdigit(static_cast<unsigned char>(Name[0]))) {
29603b80a40SChris Lattner         SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
29703b80a40SChris Lattner                         "invalid name in named regex");
2988879e06dSChris Lattner         return true;
2998879e06dSChris Lattner       }
3008879e06dSChris Lattner 
3018879e06dSChris Lattner       // Handle [[foo]].
3028879e06dSChris Lattner       if (NameEnd == StringRef::npos) {
303e8b8f1bcSEli Bendersky         // Handle variables that were defined earlier on the same line by
304e8b8f1bcSEli Bendersky         // emitting a backreference.
305e8b8f1bcSEli Bendersky         if (VariableDefs.find(Name) != VariableDefs.end()) {
306e8b8f1bcSEli Bendersky           unsigned VarParenNum = VariableDefs[Name];
307e8b8f1bcSEli Bendersky           if (VarParenNum < 1 || VarParenNum > 9) {
308e8b8f1bcSEli Bendersky             SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
309e8b8f1bcSEli Bendersky                             SourceMgr::DK_Error,
310e8b8f1bcSEli Bendersky                             "Can't back-reference more than 9 variables");
311e8b8f1bcSEli Bendersky             return true;
312e8b8f1bcSEli Bendersky           }
313e8b8f1bcSEli Bendersky           AddBackrefToRegEx(VarParenNum);
314e8b8f1bcSEli Bendersky         } else {
3158879e06dSChris Lattner           VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
316e8b8f1bcSEli Bendersky         }
3178879e06dSChris Lattner         continue;
3188879e06dSChris Lattner       }
3198879e06dSChris Lattner 
3208879e06dSChris Lattner       // Handle [[foo:.*]].
321e8b8f1bcSEli Bendersky       VariableDefs[Name] = CurParen;
3228879e06dSChris Lattner       RegExStr += '(';
3238879e06dSChris Lattner       ++CurParen;
3248879e06dSChris Lattner 
3258879e06dSChris Lattner       if (AddRegExToRegEx(MatchStr.substr(NameEnd + 1), CurParen, SM))
3268879e06dSChris Lattner         return true;
3278879e06dSChris Lattner 
3288879e06dSChris Lattner       RegExStr += ')';
3298879e06dSChris Lattner     }
3308879e06dSChris Lattner 
3318879e06dSChris Lattner     // Handle fixed string matches.
3328879e06dSChris Lattner     // Find the end, which is the start of the next regex.
3338879e06dSChris Lattner     size_t FixedMatchEnd = PatternStr.find("{{");
3348879e06dSChris Lattner     FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
3356f4f77b7SHans Wennborg     RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
3368879e06dSChris Lattner     PatternStr = PatternStr.substr(FixedMatchEnd);
337f08d2db9SChris Lattner   }
338f08d2db9SChris Lattner 
33985913ccaSJames Y Knight   if (MatchFullLinesHere) {
34085913ccaSJames Y Knight     if (!NoCanonicalizeWhiteSpace)
34185913ccaSJames Y Knight       RegExStr += " *";
34285913ccaSJames Y Knight     RegExStr += '$';
34385913ccaSJames Y Knight   }
34485913ccaSJames Y Knight 
34574d50731SChris Lattner   return false;
34674d50731SChris Lattner }
34774d50731SChris Lattner 
348e8f2fb20SChandler Carruth bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
349e8b8f1bcSEli Bendersky   Regex R(RS);
3508879e06dSChris Lattner   std::string Error;
3518879e06dSChris Lattner   if (!R.isValid(Error)) {
352e8b8f1bcSEli Bendersky     SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
35303b80a40SChris Lattner                     "invalid regex: " + Error);
3548879e06dSChris Lattner     return true;
3558879e06dSChris Lattner   }
3568879e06dSChris Lattner 
357e8b8f1bcSEli Bendersky   RegExStr += RS.str();
3588879e06dSChris Lattner   CurParen += R.getNumMatches();
3598879e06dSChris Lattner   return false;
3608879e06dSChris Lattner }
361b16ab0c4SChris Lattner 
362e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
363e8b8f1bcSEli Bendersky   assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
364e8f2fb20SChandler Carruth   std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
365e8b8f1bcSEli Bendersky   RegExStr += Backref;
366e8b8f1bcSEli Bendersky }
367e8b8f1bcSEli Bendersky 
3684dabac20SChandler Carruth /// Evaluates expression and stores the result to \p Value.
3694dabac20SChandler Carruth ///
3704dabac20SChandler Carruth /// Returns true on success and false when the expression has invalid syntax.
37192987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
37292987fb3SAlexander Kornienko   // The only supported expression is @LINE([\+-]\d+)?
37392987fb3SAlexander Kornienko   if (!Expr.startswith("@LINE"))
37492987fb3SAlexander Kornienko     return false;
37592987fb3SAlexander Kornienko   Expr = Expr.substr(StringRef("@LINE").size());
37692987fb3SAlexander Kornienko   int Offset = 0;
37792987fb3SAlexander Kornienko   if (!Expr.empty()) {
37892987fb3SAlexander Kornienko     if (Expr[0] == '+')
37992987fb3SAlexander Kornienko       Expr = Expr.substr(1);
38092987fb3SAlexander Kornienko     else if (Expr[0] != '-')
38192987fb3SAlexander Kornienko       return false;
38292987fb3SAlexander Kornienko     if (Expr.getAsInteger(10, Offset))
38392987fb3SAlexander Kornienko       return false;
38492987fb3SAlexander Kornienko   }
38592987fb3SAlexander Kornienko   Value = llvm::itostr(LineNumber + Offset);
38692987fb3SAlexander Kornienko   return true;
38792987fb3SAlexander Kornienko }
38892987fb3SAlexander Kornienko 
3894dabac20SChandler Carruth /// Matches the pattern string against the input buffer \p Buffer
3904dabac20SChandler Carruth ///
3914dabac20SChandler Carruth /// This returns the position that is matched or npos if there is no match. If
3924dabac20SChandler Carruth /// there is a match, the size of the matched string is returned in \p
3934dabac20SChandler Carruth /// MatchLen.
3944dabac20SChandler Carruth ///
3954dabac20SChandler Carruth /// The \p VariableTable StringMap provides the current values of filecheck
3964dabac20SChandler Carruth /// variables and is updated if this match defines new values.
3978879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
3988879e06dSChris Lattner                       StringMap<StringRef> &VariableTable) const {
399eba55822SJakob Stoklund Olesen   // If this is the EOF pattern, match it immediately.
40038820972SMatt Arsenault   if (CheckTy == Check::CheckEOF) {
401eba55822SJakob Stoklund Olesen     MatchLen = 0;
402eba55822SJakob Stoklund Olesen     return Buffer.size();
403eba55822SJakob Stoklund Olesen   }
404eba55822SJakob Stoklund Olesen 
405221460e0SChris Lattner   // If this is a fixed string pattern, just match it now.
406221460e0SChris Lattner   if (!FixedStr.empty()) {
407221460e0SChris Lattner     MatchLen = FixedStr.size();
408221460e0SChris Lattner     return Buffer.find(FixedStr);
409221460e0SChris Lattner   }
410221460e0SChris Lattner 
411b16ab0c4SChris Lattner   // Regex match.
4128879e06dSChris Lattner 
4138879e06dSChris Lattner   // If there are variable uses, we need to create a temporary string with the
4148879e06dSChris Lattner   // actual value.
4158879e06dSChris Lattner   StringRef RegExToMatch = RegExStr;
4168879e06dSChris Lattner   std::string TmpStr;
4178879e06dSChris Lattner   if (!VariableUses.empty()) {
4188879e06dSChris Lattner     TmpStr = RegExStr;
4198879e06dSChris Lattner 
4208879e06dSChris Lattner     unsigned InsertOffset = 0;
4218f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
42292987fb3SAlexander Kornienko       std::string Value;
42392987fb3SAlexander Kornienko 
4248f870499SBenjamin Kramer       if (VariableUse.first[0] == '@') {
4258f870499SBenjamin Kramer         if (!EvaluateExpression(VariableUse.first, Value))
42692987fb3SAlexander Kornienko           return StringRef::npos;
42792987fb3SAlexander Kornienko       } else {
428e0ef65abSDaniel Dunbar         StringMap<StringRef>::iterator it =
4298f870499SBenjamin Kramer             VariableTable.find(VariableUse.first);
430e0ef65abSDaniel Dunbar         // If the variable is undefined, return an error.
431e0ef65abSDaniel Dunbar         if (it == VariableTable.end())
432e0ef65abSDaniel Dunbar           return StringRef::npos;
433e0ef65abSDaniel Dunbar 
4346f4f77b7SHans Wennborg         // Look up the value and escape it so that we can put it into the regex.
4356f4f77b7SHans Wennborg         Value += Regex::escape(it->second);
43692987fb3SAlexander Kornienko       }
4378879e06dSChris Lattner 
4388879e06dSChris Lattner       // Plop it into the regex at the adjusted offset.
4398f870499SBenjamin Kramer       TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset,
4408879e06dSChris Lattner                     Value.begin(), Value.end());
4418879e06dSChris Lattner       InsertOffset += Value.size();
4428879e06dSChris Lattner     }
4438879e06dSChris Lattner 
4448879e06dSChris Lattner     // Match the newly constructed regex.
4458879e06dSChris Lattner     RegExToMatch = TmpStr;
4468879e06dSChris Lattner   }
4478879e06dSChris Lattner 
448b16ab0c4SChris Lattner   SmallVector<StringRef, 4> MatchInfo;
4498879e06dSChris Lattner   if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
450f08d2db9SChris Lattner     return StringRef::npos;
451b16ab0c4SChris Lattner 
452b16ab0c4SChris Lattner   // Successful regex match.
453b16ab0c4SChris Lattner   assert(!MatchInfo.empty() && "Didn't get any match");
454b16ab0c4SChris Lattner   StringRef FullMatch = MatchInfo[0];
455b16ab0c4SChris Lattner 
4568879e06dSChris Lattner   // If this defines any variables, remember their values.
4578f870499SBenjamin Kramer   for (const auto &VariableDef : VariableDefs) {
4588f870499SBenjamin Kramer     assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
4598f870499SBenjamin Kramer     VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
4600a4c44bdSChris Lattner   }
4610a4c44bdSChris Lattner 
462b16ab0c4SChris Lattner   MatchLen = FullMatch.size();
463b16ab0c4SChris Lattner   return FullMatch.data() - Buffer.data();
464f08d2db9SChris Lattner }
465f08d2db9SChris Lattner 
4664dabac20SChandler Carruth 
4674dabac20SChandler Carruth /// Computes an arbitrary estimate for the quality of matching this pattern at
4684dabac20SChandler Carruth /// the start of \p Buffer; a distance of zero should correspond to a perfect
4694dabac20SChandler Carruth /// match.
470e8f2fb20SChandler Carruth unsigned
471e8f2fb20SChandler Carruth Pattern::ComputeMatchDistance(StringRef Buffer,
472fd29d886SDaniel Dunbar                               const StringMap<StringRef> &VariableTable) const {
473fd29d886SDaniel Dunbar   // Just compute the number of matching characters. For regular expressions, we
474fd29d886SDaniel Dunbar   // just compare against the regex itself and hope for the best.
475fd29d886SDaniel Dunbar   //
476fd29d886SDaniel Dunbar   // FIXME: One easy improvement here is have the regex lib generate a single
477fd29d886SDaniel Dunbar   // example regular expression which matches, and use that as the example
478fd29d886SDaniel Dunbar   // string.
479fd29d886SDaniel Dunbar   StringRef ExampleString(FixedStr);
480fd29d886SDaniel Dunbar   if (ExampleString.empty())
481fd29d886SDaniel Dunbar     ExampleString = RegExStr;
482fd29d886SDaniel Dunbar 
483e9aa36c8SDaniel Dunbar   // Only compare up to the first line in the buffer, or the string size.
484e9aa36c8SDaniel Dunbar   StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
485e9aa36c8SDaniel Dunbar   BufferPrefix = BufferPrefix.split('\n').first;
486e9aa36c8SDaniel Dunbar   return BufferPrefix.edit_distance(ExampleString);
487fd29d886SDaniel Dunbar }
488fd29d886SDaniel Dunbar 
4894dabac20SChandler Carruth /// Prints additional information about a failure to match involving this
4904dabac20SChandler Carruth /// pattern.
491e8f2fb20SChandler Carruth void Pattern::PrintFailureInfo(
492e8f2fb20SChandler Carruth     const SourceMgr &SM, StringRef Buffer,
493e0ef65abSDaniel Dunbar     const StringMap<StringRef> &VariableTable) const {
494e0ef65abSDaniel Dunbar   // If this was a regular expression using variables, print the current
495e0ef65abSDaniel Dunbar   // variable values.
496e0ef65abSDaniel Dunbar   if (!VariableUses.empty()) {
4978f870499SBenjamin Kramer     for (const auto &VariableUse : VariableUses) {
498e69170a1SAlp Toker       SmallString<256> Msg;
499e69170a1SAlp Toker       raw_svector_ostream OS(Msg);
5008f870499SBenjamin Kramer       StringRef Var = VariableUse.first;
50192987fb3SAlexander Kornienko       if (Var[0] == '@') {
50292987fb3SAlexander Kornienko         std::string Value;
50392987fb3SAlexander Kornienko         if (EvaluateExpression(Var, Value)) {
50492987fb3SAlexander Kornienko           OS << "with expression \"";
50592987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\" equal to \"";
50692987fb3SAlexander Kornienko           OS.write_escaped(Value) << "\"";
50792987fb3SAlexander Kornienko         } else {
50892987fb3SAlexander Kornienko           OS << "uses incorrect expression \"";
50992987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
51092987fb3SAlexander Kornienko         }
51192987fb3SAlexander Kornienko       } else {
51292987fb3SAlexander Kornienko         StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
513e0ef65abSDaniel Dunbar 
514e0ef65abSDaniel Dunbar         // Check for undefined variable references.
515e0ef65abSDaniel Dunbar         if (it == VariableTable.end()) {
516e0ef65abSDaniel Dunbar           OS << "uses undefined variable \"";
51792987fb3SAlexander Kornienko           OS.write_escaped(Var) << "\"";
518e0ef65abSDaniel Dunbar         } else {
519e0ef65abSDaniel Dunbar           OS << "with variable \"";
520e0ef65abSDaniel Dunbar           OS.write_escaped(Var) << "\" equal to \"";
521e0ef65abSDaniel Dunbar           OS.write_escaped(it->second) << "\"";
522e0ef65abSDaniel Dunbar         }
52392987fb3SAlexander Kornienko       }
524e0ef65abSDaniel Dunbar 
52503b80a40SChris Lattner       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
52603b80a40SChris Lattner                       OS.str());
527e0ef65abSDaniel Dunbar     }
528e0ef65abSDaniel Dunbar   }
529fd29d886SDaniel Dunbar 
530fd29d886SDaniel Dunbar   // Attempt to find the closest/best fuzzy match.  Usually an error happens
531fd29d886SDaniel Dunbar   // because some string in the output didn't exactly match. In these cases, we
532fd29d886SDaniel Dunbar   // would like to show the user a best guess at what "should have" matched, to
533fd29d886SDaniel Dunbar   // save them having to actually check the input manually.
534fd29d886SDaniel Dunbar   size_t NumLinesForward = 0;
535fd29d886SDaniel Dunbar   size_t Best = StringRef::npos;
536fd29d886SDaniel Dunbar   double BestQuality = 0;
537fd29d886SDaniel Dunbar 
538fd29d886SDaniel Dunbar   // Use an arbitrary 4k limit on how far we will search.
5392bf486ebSDan Gohman   for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
540fd29d886SDaniel Dunbar     if (Buffer[i] == '\n')
541fd29d886SDaniel Dunbar       ++NumLinesForward;
542fd29d886SDaniel Dunbar 
543df22bbf7SDan Gohman     // Patterns have leading whitespace stripped, so skip whitespace when
544df22bbf7SDan Gohman     // looking for something which looks like a pattern.
545df22bbf7SDan Gohman     if (Buffer[i] == ' ' || Buffer[i] == '\t')
546df22bbf7SDan Gohman       continue;
547df22bbf7SDan Gohman 
548fd29d886SDaniel Dunbar     // Compute the "quality" of this match as an arbitrary combination of the
549fd29d886SDaniel Dunbar     // match distance and the number of lines skipped to get to this match.
550fd29d886SDaniel Dunbar     unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
551fd29d886SDaniel Dunbar     double Quality = Distance + (NumLinesForward / 100.);
552fd29d886SDaniel Dunbar 
553fd29d886SDaniel Dunbar     if (Quality < BestQuality || Best == StringRef::npos) {
554fd29d886SDaniel Dunbar       Best = i;
555fd29d886SDaniel Dunbar       BestQuality = Quality;
556fd29d886SDaniel Dunbar     }
557fd29d886SDaniel Dunbar   }
558fd29d886SDaniel Dunbar 
559fd29d886SDaniel Dunbar   // Print the "possible intended match here" line if we found something
560c069cc8eSDaniel Dunbar   // reasonable and not equal to what we showed in the "scanning from here"
561c069cc8eSDaniel Dunbar   // line.
562c069cc8eSDaniel Dunbar   if (Best && Best != StringRef::npos && BestQuality < 50) {
563fd29d886SDaniel Dunbar     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
56403b80a40SChris Lattner                     SourceMgr::DK_Note, "possible intended match here");
565fd29d886SDaniel Dunbar 
566fd29d886SDaniel Dunbar     // FIXME: If we wanted to be really friendly we would show why the match
567fd29d886SDaniel Dunbar     // failed, as it can be hard to spot simple one character differences.
568fd29d886SDaniel Dunbar   }
569e0ef65abSDaniel Dunbar }
57074d50731SChris Lattner 
5714dabac20SChandler Carruth /// Finds the closing sequence of a regex variable usage or definition.
5724dabac20SChandler Carruth ///
5734dabac20SChandler Carruth /// \p Str has to point in the beginning of the definition (right after the
5744dabac20SChandler Carruth /// opening sequence). Returns the offset of the closing sequence within Str,
5754dabac20SChandler Carruth /// or npos if it was not found.
57681e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
577061d2baaSEli Bendersky   // Offset keeps track of the current offset within the input Str
578061d2baaSEli Bendersky   size_t Offset = 0;
579061d2baaSEli Bendersky   // [...] Nesting depth
580061d2baaSEli Bendersky   size_t BracketDepth = 0;
581061d2baaSEli Bendersky 
582061d2baaSEli Bendersky   while (!Str.empty()) {
583061d2baaSEli Bendersky     if (Str.startswith("]]") && BracketDepth == 0)
584061d2baaSEli Bendersky       return Offset;
585061d2baaSEli Bendersky     if (Str[0] == '\\') {
586061d2baaSEli Bendersky       // Backslash escapes the next char within regexes, so skip them both.
587061d2baaSEli Bendersky       Str = Str.substr(2);
588061d2baaSEli Bendersky       Offset += 2;
589061d2baaSEli Bendersky     } else {
590061d2baaSEli Bendersky       switch (Str[0]) {
591061d2baaSEli Bendersky       default:
592061d2baaSEli Bendersky         break;
593061d2baaSEli Bendersky       case '[':
594061d2baaSEli Bendersky         BracketDepth++;
595061d2baaSEli Bendersky         break;
596061d2baaSEli Bendersky       case ']':
59781e5cd9eSAdrian Prantl         if (BracketDepth == 0) {
59881e5cd9eSAdrian Prantl           SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
59981e5cd9eSAdrian Prantl                           SourceMgr::DK_Error,
60081e5cd9eSAdrian Prantl                           "missing closing \"]\" for regex variable");
60181e5cd9eSAdrian Prantl           exit(1);
60281e5cd9eSAdrian Prantl         }
603061d2baaSEli Bendersky         BracketDepth--;
604061d2baaSEli Bendersky         break;
605061d2baaSEli Bendersky       }
606061d2baaSEli Bendersky       Str = Str.substr(1);
607061d2baaSEli Bendersky       Offset++;
608061d2baaSEli Bendersky     }
609061d2baaSEli Bendersky   }
610061d2baaSEli Bendersky 
611061d2baaSEli Bendersky   return StringRef::npos;
612061d2baaSEli Bendersky }
613061d2baaSEli Bendersky 
61474d50731SChris Lattner //===----------------------------------------------------------------------===//
61574d50731SChris Lattner // Check Strings.
61674d50731SChris Lattner //===----------------------------------------------------------------------===//
6173b40b445SChris Lattner 
6184dabac20SChandler Carruth /// A check that we found in the input file.
6193b40b445SChris Lattner struct CheckString {
6204dabac20SChandler Carruth   /// The pattern to match.
6213b40b445SChris Lattner   Pattern Pat;
62226cccfe1SChris Lattner 
6234dabac20SChandler Carruth   /// Which prefix name this check matched.
62413df4626SMatt Arsenault   StringRef Prefix;
62513df4626SMatt Arsenault 
6264dabac20SChandler Carruth   /// The location in the match file that the check string was specified.
62726cccfe1SChris Lattner   SMLoc Loc;
62826cccfe1SChris Lattner 
6294dabac20SChandler Carruth   /// All of the strings that are disallowed from occurring between this match
6304dabac20SChandler Carruth   /// string and the previous one (or start of file).
63191a1b2c9SMichael Liao   std::vector<Pattern> DagNotStrings;
632236d2d5eSChris Lattner 
63385913ccaSJames Y Knight   CheckString(const Pattern &P, StringRef S, SMLoc L)
63485913ccaSJames Y Knight       : Pat(P), Prefix(S), Loc(L) {}
635dcc7d48dSMichael Liao 
636e93a3a08SStephen Lin   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
637f8bd2e5bSStephen Lin                size_t &MatchLen, StringMap<StringRef> &VariableTable) const;
638dcc7d48dSMichael Liao 
639dcc7d48dSMichael Liao   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
64001ac1707SDuncan P. N. Exon Smith   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
641dcc7d48dSMichael Liao   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
64291a1b2c9SMichael Liao                 const std::vector<const Pattern *> &NotStrings,
64391a1b2c9SMichael Liao                 StringMap<StringRef> &VariableTable) const;
64491a1b2c9SMichael Liao   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
64591a1b2c9SMichael Liao                   std::vector<const Pattern *> &NotStrings,
646dcc7d48dSMichael Liao                   StringMap<StringRef> &VariableTable) const;
64726cccfe1SChris Lattner };
64826cccfe1SChris Lattner 
64920247900SChandler Carruth /// Canonicalize whitespaces in the file. Line endings are replaced with
65020247900SChandler Carruth /// UNIX-style '\n'.
651b03c166aSChandler Carruth static StringRef CanonicalizeFile(MemoryBuffer &MB,
65220247900SChandler Carruth                                   SmallVectorImpl<char> &OutputBuffer) {
65320247900SChandler Carruth   OutputBuffer.reserve(MB.getBufferSize());
654a2f8fc5aSChris Lattner 
65520247900SChandler Carruth   for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
656a2f8fc5aSChris Lattner        Ptr != End; ++Ptr) {
657fd781bf0SNAKAMURA Takumi     // Eliminate trailing dosish \r.
658fd781bf0SNAKAMURA Takumi     if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
659fd781bf0SNAKAMURA Takumi       continue;
660fd781bf0SNAKAMURA Takumi     }
661fd781bf0SNAKAMURA Takumi 
6625ea04c38SGuy Benyei     // If current char is not a horizontal whitespace or if horizontal
6635ea04c38SGuy Benyei     // whitespace canonicalization is disabled, dump it to output as is.
664b03c166aSChandler Carruth     if (NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
66520247900SChandler Carruth       OutputBuffer.push_back(*Ptr);
666a2f8fc5aSChris Lattner       continue;
667a2f8fc5aSChris Lattner     }
668a2f8fc5aSChris Lattner 
669a2f8fc5aSChris Lattner     // Otherwise, add one space and advance over neighboring space.
67020247900SChandler Carruth     OutputBuffer.push_back(' ');
671e8f2fb20SChandler Carruth     while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
672a2f8fc5aSChris Lattner       ++Ptr;
673a2f8fc5aSChris Lattner   }
674a2f8fc5aSChris Lattner 
67520247900SChandler Carruth   // Add a null byte and then return all but that byte.
67620247900SChandler Carruth   OutputBuffer.push_back('\0');
67720247900SChandler Carruth   return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
678a2f8fc5aSChris Lattner }
679a2f8fc5aSChris Lattner 
68038820972SMatt Arsenault static bool IsPartOfWord(char c) {
68138820972SMatt Arsenault   return (isalnum(c) || c == '-' || c == '_');
68238820972SMatt Arsenault }
68338820972SMatt Arsenault 
68413df4626SMatt Arsenault // Get the size of the prefix extension.
68513df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) {
68613df4626SMatt Arsenault   switch (Ty) {
68713df4626SMatt Arsenault   case Check::CheckNone:
688a908e7bdSPaul Robinson   case Check::CheckBadNot:
68913df4626SMatt Arsenault     return 0;
69013df4626SMatt Arsenault 
69113df4626SMatt Arsenault   case Check::CheckPlain:
69213df4626SMatt Arsenault     return sizeof(":") - 1;
69313df4626SMatt Arsenault 
69413df4626SMatt Arsenault   case Check::CheckNext:
69513df4626SMatt Arsenault     return sizeof("-NEXT:") - 1;
69613df4626SMatt Arsenault 
69701ac1707SDuncan P. N. Exon Smith   case Check::CheckSame:
69801ac1707SDuncan P. N. Exon Smith     return sizeof("-SAME:") - 1;
69901ac1707SDuncan P. N. Exon Smith 
70013df4626SMatt Arsenault   case Check::CheckNot:
70113df4626SMatt Arsenault     return sizeof("-NOT:") - 1;
70213df4626SMatt Arsenault 
70313df4626SMatt Arsenault   case Check::CheckDAG:
70413df4626SMatt Arsenault     return sizeof("-DAG:") - 1;
70513df4626SMatt Arsenault 
70613df4626SMatt Arsenault   case Check::CheckLabel:
70713df4626SMatt Arsenault     return sizeof("-LABEL:") - 1;
70813df4626SMatt Arsenault 
70913df4626SMatt Arsenault   case Check::CheckEOF:
71013df4626SMatt Arsenault     llvm_unreachable("Should not be using EOF size");
71113df4626SMatt Arsenault   }
71213df4626SMatt Arsenault 
71313df4626SMatt Arsenault   llvm_unreachable("Bad check type");
71413df4626SMatt Arsenault }
71513df4626SMatt Arsenault 
71613df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
717c4d2d471SMatt Arsenault   char NextChar = Buffer[Prefix.size()];
71838820972SMatt Arsenault 
71938820972SMatt Arsenault   // Verify that the : is present after the prefix.
72013df4626SMatt Arsenault   if (NextChar == ':')
72138820972SMatt Arsenault     return Check::CheckPlain;
72238820972SMatt Arsenault 
72313df4626SMatt Arsenault   if (NextChar != '-')
72438820972SMatt Arsenault     return Check::CheckNone;
72538820972SMatt Arsenault 
726c4d2d471SMatt Arsenault   StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
72713df4626SMatt Arsenault   if (Rest.startswith("NEXT:"))
72838820972SMatt Arsenault     return Check::CheckNext;
72938820972SMatt Arsenault 
73001ac1707SDuncan P. N. Exon Smith   if (Rest.startswith("SAME:"))
73101ac1707SDuncan P. N. Exon Smith     return Check::CheckSame;
73201ac1707SDuncan P. N. Exon Smith 
73313df4626SMatt Arsenault   if (Rest.startswith("NOT:"))
73438820972SMatt Arsenault     return Check::CheckNot;
73538820972SMatt Arsenault 
73613df4626SMatt Arsenault   if (Rest.startswith("DAG:"))
73738820972SMatt Arsenault     return Check::CheckDAG;
73838820972SMatt Arsenault 
73913df4626SMatt Arsenault   if (Rest.startswith("LABEL:"))
74038820972SMatt Arsenault     return Check::CheckLabel;
74113df4626SMatt Arsenault 
742a908e7bdSPaul Robinson   // You can't combine -NOT with another suffix.
743a908e7bdSPaul Robinson   if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
744a908e7bdSPaul Robinson       Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
745a908e7bdSPaul Robinson       Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:"))
746a908e7bdSPaul Robinson     return Check::CheckBadNot;
747a908e7bdSPaul Robinson 
74813df4626SMatt Arsenault   return Check::CheckNone;
74938820972SMatt Arsenault }
75038820972SMatt Arsenault 
75113df4626SMatt Arsenault // From the given position, find the next character after the word.
75213df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) {
75313df4626SMatt Arsenault   while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
75413df4626SMatt Arsenault     ++Loc;
75513df4626SMatt Arsenault   return Loc;
75613df4626SMatt Arsenault }
75713df4626SMatt Arsenault 
758726774cbSChandler Carruth /// Search the buffer for the first prefix in the prefix regular expression.
759726774cbSChandler Carruth ///
760726774cbSChandler Carruth /// This searches the buffer using the provided regular expression, however it
761726774cbSChandler Carruth /// enforces constraints beyond that:
762726774cbSChandler Carruth /// 1) The found prefix must not be a suffix of something that looks like
763726774cbSChandler Carruth ///    a valid prefix.
764726774cbSChandler Carruth /// 2) The found prefix must be followed by a valid check type suffix using \c
765726774cbSChandler Carruth ///    FindCheckType above.
766726774cbSChandler Carruth ///
767726774cbSChandler Carruth /// The first match of the regular expression to satisfy these two is returned,
768726774cbSChandler Carruth /// otherwise an empty StringRef is returned to indicate failure.
769726774cbSChandler Carruth ///
770726774cbSChandler Carruth /// If this routine returns a valid prefix, it will also shrink \p Buffer to
771726774cbSChandler Carruth /// start at the beginning of the returned prefix, increment \p LineNumber for
772726774cbSChandler Carruth /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
773726774cbSChandler Carruth /// check found by examining the suffix.
774726774cbSChandler Carruth ///
775726774cbSChandler Carruth /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
776726774cbSChandler Carruth /// is unspecified.
777726774cbSChandler Carruth static StringRef FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
77813df4626SMatt Arsenault                                          unsigned &LineNumber,
779726774cbSChandler Carruth                                          Check::CheckType &CheckTy) {
780726774cbSChandler Carruth   SmallVector<StringRef, 2> Matches;
781726774cbSChandler Carruth 
78213df4626SMatt Arsenault   while (!Buffer.empty()) {
783726774cbSChandler Carruth     // Find the first (longest) match using the RE.
784726774cbSChandler Carruth     if (!PrefixRE.match(Buffer, &Matches))
785726774cbSChandler Carruth       // No match at all, bail.
786726774cbSChandler Carruth       return StringRef();
787726774cbSChandler Carruth 
788726774cbSChandler Carruth     StringRef Prefix = Matches[0];
789726774cbSChandler Carruth     Matches.clear();
790726774cbSChandler Carruth 
791726774cbSChandler Carruth     assert(Prefix.data() >= Buffer.data() &&
792726774cbSChandler Carruth            Prefix.data() < Buffer.data() + Buffer.size() &&
793726774cbSChandler Carruth            "Prefix doesn't start inside of buffer!");
794726774cbSChandler Carruth     size_t Loc = Prefix.data() - Buffer.data();
795726774cbSChandler Carruth     StringRef Skipped = Buffer.substr(0, Loc);
796726774cbSChandler Carruth     Buffer = Buffer.drop_front(Loc);
797726774cbSChandler Carruth     LineNumber += Skipped.count('\n');
798726774cbSChandler Carruth 
799726774cbSChandler Carruth     // Check that the matched prefix isn't a suffix of some other check-like
800726774cbSChandler Carruth     // word.
801726774cbSChandler Carruth     // FIXME: This is a very ad-hoc check. it would be better handled in some
802726774cbSChandler Carruth     // other way. Among other things it seems hard to distinguish between
803726774cbSChandler Carruth     // intentional and unintentional uses of this feature.
804726774cbSChandler Carruth     if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
805726774cbSChandler Carruth       // Now extract the type.
806726774cbSChandler Carruth       CheckTy = FindCheckType(Buffer, Prefix);
807726774cbSChandler Carruth 
808726774cbSChandler Carruth       // If we've found a valid check type for this prefix, we're done.
809726774cbSChandler Carruth       if (CheckTy != Check::CheckNone)
81013df4626SMatt Arsenault         return Prefix;
81113df4626SMatt Arsenault     }
81213df4626SMatt Arsenault 
813726774cbSChandler Carruth     // If we didn't successfully find a prefix, we need to skip this invalid
814726774cbSChandler Carruth     // prefix and continue scanning. We directly skip the prefix that was
815726774cbSChandler Carruth     // matched and any additional parts of that check-like word.
816726774cbSChandler Carruth     Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
81713df4626SMatt Arsenault   }
81813df4626SMatt Arsenault 
819726774cbSChandler Carruth   // We ran out of buffer while skipping partial matches so give up.
82013df4626SMatt Arsenault   return StringRef();
82138820972SMatt Arsenault }
822ee3c74fbSChris Lattner 
8234dabac20SChandler Carruth /// Read the check file, which specifies the sequence of expected strings.
8244dabac20SChandler Carruth ///
8254dabac20SChandler Carruth /// The strings are added to the CheckStrings vector. Returns true in case of
8264dabac20SChandler Carruth /// an error, false otherwise.
827726774cbSChandler Carruth static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
82826cccfe1SChris Lattner                           std::vector<CheckString> &CheckStrings) {
82956ccdbbdSAlexander Kornienko   std::vector<Pattern> ImplicitNegativeChecks;
83056ccdbbdSAlexander Kornienko   for (const auto &PatternString : ImplicitCheckNot) {
83156ccdbbdSAlexander Kornienko     // Create a buffer with fake command line content in order to display the
83256ccdbbdSAlexander Kornienko     // command line option responsible for the specific implicit CHECK-NOT.
833ff43d69dSDavid Blaikie     std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str();
83456ccdbbdSAlexander Kornienko     std::string Suffix = "'";
8353560ff2cSRafael Espindola     std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
8363560ff2cSRafael Espindola         Prefix + PatternString + Suffix, "command line");
8373560ff2cSRafael Espindola 
83856ccdbbdSAlexander Kornienko     StringRef PatternInBuffer =
83956ccdbbdSAlexander Kornienko         CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
8401961f14cSDavid Blaikie     SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
84156ccdbbdSAlexander Kornienko 
84256ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot));
84356ccdbbdSAlexander Kornienko     ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
84456ccdbbdSAlexander Kornienko                                                "IMPLICIT-CHECK", SM, 0);
84556ccdbbdSAlexander Kornienko   }
84656ccdbbdSAlexander Kornienko 
84756ccdbbdSAlexander Kornienko   std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
848236d2d5eSChris Lattner 
84943d50d4aSEli Bendersky   // LineNumber keeps track of the line on which CheckPrefix instances are
85043d50d4aSEli Bendersky   // found.
85192987fb3SAlexander Kornienko   unsigned LineNumber = 1;
85292987fb3SAlexander Kornienko 
853ee3c74fbSChris Lattner   while (1) {
85413df4626SMatt Arsenault     Check::CheckType CheckTy;
85513df4626SMatt Arsenault 
85613df4626SMatt Arsenault     // See if a prefix occurs in the memory buffer.
857726774cbSChandler Carruth     StringRef UsedPrefix = FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber,
858726774cbSChandler Carruth                                                    CheckTy);
85913df4626SMatt Arsenault     if (UsedPrefix.empty())
860ee3c74fbSChris Lattner       break;
861726774cbSChandler Carruth     assert(UsedPrefix.data() == Buffer.data() &&
862726774cbSChandler Carruth            "Failed to move Buffer's start forward, or pointed prefix outside "
863726774cbSChandler Carruth            "of the buffer!");
86492987fb3SAlexander Kornienko 
86513df4626SMatt Arsenault     // Location to use for error messages.
866726774cbSChandler Carruth     const char *UsedPrefixStart = UsedPrefix.data();
86792987fb3SAlexander Kornienko 
868726774cbSChandler Carruth     // Skip the buffer to the end.
86913df4626SMatt Arsenault     Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
87010f10cedSChris Lattner 
871a908e7bdSPaul Robinson     // Complain about useful-looking but unsupported suffixes.
872a908e7bdSPaul Robinson     if (CheckTy == Check::CheckBadNot) {
873e8f2fb20SChandler Carruth       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
874a908e7bdSPaul Robinson                       "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
875a908e7bdSPaul Robinson       return true;
876a908e7bdSPaul Robinson     }
877a908e7bdSPaul Robinson 
87838820972SMatt Arsenault     // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
879a26bc914STom de Vries     // leading whitespace.
8801714676aSTom de Vries     if (!(NoCanonicalizeWhiteSpace && MatchFullLines))
881236d2d5eSChris Lattner       Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
882ee3c74fbSChris Lattner 
883ee3c74fbSChris Lattner     // Scan ahead to the end of line.
884caa5fc0cSChris Lattner     size_t EOL = Buffer.find_first_of("\n\r");
885ee3c74fbSChris Lattner 
886838fb09aSDan Gohman     // Remember the location of the start of the pattern, for diagnostics.
887838fb09aSDan Gohman     SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
888838fb09aSDan Gohman 
88974d50731SChris Lattner     // Parse the pattern.
89038820972SMatt Arsenault     Pattern P(CheckTy);
89113df4626SMatt Arsenault     if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber))
892ee3c74fbSChris Lattner       return true;
893ee3c74fbSChris Lattner 
894f8bd2e5bSStephen Lin     // Verify that CHECK-LABEL lines do not define or use variables
89538820972SMatt Arsenault     if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
896e8f2fb20SChandler Carruth       SM.PrintMessage(
897e8f2fb20SChandler Carruth           SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
89813df4626SMatt Arsenault           "found '" + UsedPrefix + "-LABEL:'"
89913df4626SMatt Arsenault                                    " with variable definition or use");
900f8bd2e5bSStephen Lin       return true;
901f8bd2e5bSStephen Lin     }
902f8bd2e5bSStephen Lin 
903236d2d5eSChris Lattner     Buffer = Buffer.substr(EOL);
90474d50731SChris Lattner 
905da108b4eSChris Lattner     // Verify that CHECK-NEXT lines have at least one CHECK line before them.
90601ac1707SDuncan P. N. Exon Smith     if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
90701ac1707SDuncan P. N. Exon Smith         CheckStrings.empty()) {
90801ac1707SDuncan P. N. Exon Smith       StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
90913df4626SMatt Arsenault       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
91003b80a40SChris Lattner                       SourceMgr::DK_Error,
911e8f2fb20SChandler Carruth                       "found '" + UsedPrefix + "-" + Type +
912e8f2fb20SChandler Carruth                           "' without previous '" + UsedPrefix + ": line");
913da108b4eSChris Lattner       return true;
914da108b4eSChris Lattner     }
915da108b4eSChris Lattner 
91691a1b2c9SMichael Liao     // Handle CHECK-DAG/-NOT.
91738820972SMatt Arsenault     if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
91891a1b2c9SMichael Liao       DagNotMatches.push_back(P);
91974d50731SChris Lattner       continue;
92074d50731SChris Lattner     }
92174d50731SChris Lattner 
922ee3c74fbSChris Lattner     // Okay, add the string we captured to the output vector and move on.
92385913ccaSJames Y Knight     CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
92491a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
92556ccdbbdSAlexander Kornienko     DagNotMatches = ImplicitNegativeChecks;
926ee3c74fbSChris Lattner   }
927ee3c74fbSChris Lattner 
92813df4626SMatt Arsenault   // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
92913df4626SMatt Arsenault   // prefix as a filler for the error message.
93091a1b2c9SMichael Liao   if (!DagNotMatches.empty()) {
931f5e2fc47SBenjamin Kramer     CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(),
93285913ccaSJames Y Knight                               SMLoc::getFromPointer(Buffer.data()));
93391a1b2c9SMichael Liao     std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
934eba55822SJakob Stoklund Olesen   }
935eba55822SJakob Stoklund Olesen 
936ee3c74fbSChris Lattner   if (CheckStrings.empty()) {
93713df4626SMatt Arsenault     errs() << "error: no check strings found with prefix"
93813df4626SMatt Arsenault            << (CheckPrefixes.size() > 1 ? "es " : " ");
9393e3ef2f2SChris Bieneman     prefix_iterator I = CheckPrefixes.begin();
9403e3ef2f2SChris Bieneman     prefix_iterator E = CheckPrefixes.end();
9413e3ef2f2SChris Bieneman     if (I != E) {
9423e3ef2f2SChris Bieneman       errs() << "\'" << *I << ":'";
9433e3ef2f2SChris Bieneman       ++I;
94413df4626SMatt Arsenault     }
9453e3ef2f2SChris Bieneman     for (; I != E; ++I)
9463e3ef2f2SChris Bieneman       errs() << ", \'" << *I << ":'";
94713df4626SMatt Arsenault 
94813df4626SMatt Arsenault     errs() << '\n';
949ee3c74fbSChris Lattner     return true;
950ee3c74fbSChris Lattner   }
951ee3c74fbSChris Lattner 
952ee3c74fbSChris Lattner   return false;
953ee3c74fbSChris Lattner }
954ee3c74fbSChris Lattner 
955e8f2fb20SChandler Carruth static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
956e8f2fb20SChandler Carruth                              StringRef Buffer,
957e0ef65abSDaniel Dunbar                              StringMap<StringRef> &VariableTable) {
958da108b4eSChris Lattner   // Otherwise, we have an error, emit an error message.
95991a1b2c9SMichael Liao   SM.PrintMessage(Loc, SourceMgr::DK_Error,
96003b80a40SChris Lattner                   "expected string not found in input");
961da108b4eSChris Lattner 
962da108b4eSChris Lattner   // Print the "scanning from here" line.  If the current position is at the
963da108b4eSChris Lattner   // end of a line, advance to the start of the next line.
964caa5fc0cSChris Lattner   Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
965da108b4eSChris Lattner 
96603b80a40SChris Lattner   SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
96703b80a40SChris Lattner                   "scanning from here");
968e0ef65abSDaniel Dunbar 
969e0ef65abSDaniel Dunbar   // Allow the pattern to print additional information if desired.
97091a1b2c9SMichael Liao   Pat.PrintFailureInfo(SM, Buffer, VariableTable);
97191a1b2c9SMichael Liao }
97291a1b2c9SMichael Liao 
97391a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
97491a1b2c9SMichael Liao                              StringRef Buffer,
97591a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) {
97691a1b2c9SMichael Liao   PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
977da108b4eSChris Lattner }
978da108b4eSChris Lattner 
9794dabac20SChandler Carruth /// Count the number of newlines in the specified range.
980592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range,
981592fe880SRichard Smith                                         const char *&FirstNewLine) {
982da108b4eSChris Lattner   unsigned NumNewLines = 0;
98337183584SChris Lattner   while (1) {
984da108b4eSChris Lattner     // Scan for newline.
98537183584SChris Lattner     Range = Range.substr(Range.find_first_of("\n\r"));
986e8f2fb20SChandler Carruth     if (Range.empty())
987e8f2fb20SChandler Carruth       return NumNewLines;
988da108b4eSChris Lattner 
989da108b4eSChris Lattner     ++NumNewLines;
990da108b4eSChris Lattner 
991da108b4eSChris Lattner     // Handle \n\r and \r\n as a single newline.
992e8f2fb20SChandler Carruth     if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
99337183584SChris Lattner         (Range[0] != Range[1]))
99437183584SChris Lattner       Range = Range.substr(1);
99537183584SChris Lattner     Range = Range.substr(1);
996592fe880SRichard Smith 
997592fe880SRichard Smith     if (NumNewLines == 1)
998592fe880SRichard Smith       FirstNewLine = Range.begin();
999da108b4eSChris Lattner   }
1000da108b4eSChris Lattner }
1001da108b4eSChris Lattner 
10024dabac20SChandler Carruth /// Match check string and its "not strings" and/or "dag strings".
1003dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
1004e93a3a08SStephen Lin                           bool IsLabelScanMode, size_t &MatchLen,
1005dcc7d48dSMichael Liao                           StringMap<StringRef> &VariableTable) const {
100691a1b2c9SMichael Liao   size_t LastPos = 0;
100791a1b2c9SMichael Liao   std::vector<const Pattern *> NotStrings;
100891a1b2c9SMichael Liao 
1009e93a3a08SStephen Lin   // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1010e93a3a08SStephen Lin   // bounds; we have not processed variable definitions within the bounded block
1011e93a3a08SStephen Lin   // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1012e93a3a08SStephen Lin   // over the block again (including the last CHECK-LABEL) in normal mode.
1013e93a3a08SStephen Lin   if (!IsLabelScanMode) {
101491a1b2c9SMichael Liao     // Match "dag strings" (with mixed "not strings" if any).
101591a1b2c9SMichael Liao     LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable);
101691a1b2c9SMichael Liao     if (LastPos == StringRef::npos)
101791a1b2c9SMichael Liao       return StringRef::npos;
1018e93a3a08SStephen Lin   }
101991a1b2c9SMichael Liao 
102091a1b2c9SMichael Liao   // Match itself from the last position after matching CHECK-DAG.
102191a1b2c9SMichael Liao   StringRef MatchBuffer = Buffer.substr(LastPos);
102291a1b2c9SMichael Liao   size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
1023dcc7d48dSMichael Liao   if (MatchPos == StringRef::npos) {
102491a1b2c9SMichael Liao     PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
1025dcc7d48dSMichael Liao     return StringRef::npos;
1026dcc7d48dSMichael Liao   }
1027dcc7d48dSMichael Liao 
1028e93a3a08SStephen Lin   // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1029e93a3a08SStephen Lin   // or CHECK-NOT
1030e93a3a08SStephen Lin   if (!IsLabelScanMode) {
103191a1b2c9SMichael Liao     StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1032dcc7d48dSMichael Liao 
1033dcc7d48dSMichael Liao     // If this check is a "CHECK-NEXT", verify that the previous match was on
1034dcc7d48dSMichael Liao     // the previous line (i.e. that there is one newline between them).
1035dcc7d48dSMichael Liao     if (CheckNext(SM, SkippedRegion))
1036dcc7d48dSMichael Liao       return StringRef::npos;
1037dcc7d48dSMichael Liao 
103801ac1707SDuncan P. N. Exon Smith     // If this check is a "CHECK-SAME", verify that the previous match was on
103901ac1707SDuncan P. N. Exon Smith     // the same line (i.e. that there is no newline between them).
104001ac1707SDuncan P. N. Exon Smith     if (CheckSame(SM, SkippedRegion))
104101ac1707SDuncan P. N. Exon Smith       return StringRef::npos;
104201ac1707SDuncan P. N. Exon Smith 
1043dcc7d48dSMichael Liao     // If this match had "not strings", verify that they don't exist in the
1044dcc7d48dSMichael Liao     // skipped region.
104591a1b2c9SMichael Liao     if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
1046dcc7d48dSMichael Liao       return StringRef::npos;
1047f8bd2e5bSStephen Lin   }
1048dcc7d48dSMichael Liao 
10497dfb92b9SMehdi Amini   return LastPos + MatchPos;
1050dcc7d48dSMichael Liao }
1051dcc7d48dSMichael Liao 
10524dabac20SChandler Carruth /// Verify there is a single line in the given buffer.
1053dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
105485913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckNext)
1055dcc7d48dSMichael Liao     return false;
1056dcc7d48dSMichael Liao 
1057dcc7d48dSMichael Liao   // Count the number of newlines between the previous match and this one.
1058dcc7d48dSMichael Liao   assert(Buffer.data() !=
1059e8f2fb20SChandler Carruth              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
1060e8f2fb20SChandler Carruth                                     SMLoc::getFromPointer(Buffer.data())))
1061e8f2fb20SChandler Carruth                  ->getBufferStart() &&
1062dcc7d48dSMichael Liao          "CHECK-NEXT can't be the first check in a file");
1063dcc7d48dSMichael Liao 
106466f09ad0SCraig Topper   const char *FirstNewLine = nullptr;
1065592fe880SRichard Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1066dcc7d48dSMichael Liao 
1067dcc7d48dSMichael Liao   if (NumNewLines == 0) {
1068e8f2fb20SChandler Carruth     SM.PrintMessage(Loc, SourceMgr::DK_Error,
1069e8f2fb20SChandler Carruth                     Prefix + "-NEXT: is on the same line as previous match");
1070e8f2fb20SChandler Carruth     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1071e8f2fb20SChandler Carruth                     "'next' match was here");
1072dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1073dcc7d48dSMichael Liao                     "previous match ended here");
1074dcc7d48dSMichael Liao     return true;
1075dcc7d48dSMichael Liao   }
1076dcc7d48dSMichael Liao 
1077dcc7d48dSMichael Liao   if (NumNewLines != 1) {
1078e8f2fb20SChandler Carruth     SM.PrintMessage(Loc, SourceMgr::DK_Error,
1079e8f2fb20SChandler Carruth                     Prefix +
1080dcc7d48dSMichael Liao                         "-NEXT: is not on the line after the previous match");
1081e8f2fb20SChandler Carruth     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1082e8f2fb20SChandler Carruth                     "'next' match was here");
1083dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1084dcc7d48dSMichael Liao                     "previous match ended here");
1085592fe880SRichard Smith     SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
1086592fe880SRichard Smith                     "non-matching line after previous match is here");
1087dcc7d48dSMichael Liao     return true;
1088dcc7d48dSMichael Liao   }
1089dcc7d48dSMichael Liao 
1090dcc7d48dSMichael Liao   return false;
1091dcc7d48dSMichael Liao }
1092dcc7d48dSMichael Liao 
10934dabac20SChandler Carruth /// Verify there is no newline in the given buffer.
109401ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
109585913ccaSJames Y Knight   if (Pat.getCheckTy() != Check::CheckSame)
109601ac1707SDuncan P. N. Exon Smith     return false;
109701ac1707SDuncan P. N. Exon Smith 
109801ac1707SDuncan P. N. Exon Smith   // Count the number of newlines between the previous match and this one.
109901ac1707SDuncan P. N. Exon Smith   assert(Buffer.data() !=
110001ac1707SDuncan P. N. Exon Smith              SM.getMemoryBuffer(SM.FindBufferContainingLoc(
110101ac1707SDuncan P. N. Exon Smith                                     SMLoc::getFromPointer(Buffer.data())))
110201ac1707SDuncan P. N. Exon Smith                  ->getBufferStart() &&
110301ac1707SDuncan P. N. Exon Smith          "CHECK-SAME can't be the first check in a file");
110401ac1707SDuncan P. N. Exon Smith 
110501ac1707SDuncan P. N. Exon Smith   const char *FirstNewLine = nullptr;
110601ac1707SDuncan P. N. Exon Smith   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
110701ac1707SDuncan P. N. Exon Smith 
110801ac1707SDuncan P. N. Exon Smith   if (NumNewLines != 0) {
110901ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(Loc, SourceMgr::DK_Error,
111001ac1707SDuncan P. N. Exon Smith                     Prefix +
111101ac1707SDuncan P. N. Exon Smith                         "-SAME: is not on the same line as the previous match");
111201ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
111301ac1707SDuncan P. N. Exon Smith                     "'next' match was here");
111401ac1707SDuncan P. N. Exon Smith     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
111501ac1707SDuncan P. N. Exon Smith                     "previous match ended here");
111601ac1707SDuncan P. N. Exon Smith     return true;
111701ac1707SDuncan P. N. Exon Smith   }
111801ac1707SDuncan P. N. Exon Smith 
111901ac1707SDuncan P. N. Exon Smith   return false;
112001ac1707SDuncan P. N. Exon Smith }
112101ac1707SDuncan P. N. Exon Smith 
11224dabac20SChandler Carruth /// Verify there's no "not strings" in the given buffer.
1123dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
112491a1b2c9SMichael Liao                            const std::vector<const Pattern *> &NotStrings,
1125dcc7d48dSMichael Liao                            StringMap<StringRef> &VariableTable) const {
11268f870499SBenjamin Kramer   for (const Pattern *Pat : NotStrings) {
112738820972SMatt Arsenault     assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
112891a1b2c9SMichael Liao 
1129dcc7d48dSMichael Liao     size_t MatchLen = 0;
113091a1b2c9SMichael Liao     size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
1131dcc7d48dSMichael Liao 
1132e8f2fb20SChandler Carruth     if (Pos == StringRef::npos)
1133e8f2fb20SChandler Carruth       continue;
1134dcc7d48dSMichael Liao 
1135dcc7d48dSMichael Liao     SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos),
1136e8f2fb20SChandler Carruth                     SourceMgr::DK_Error, Prefix + "-NOT: string occurred!");
113791a1b2c9SMichael Liao     SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
113813df4626SMatt Arsenault                     Prefix + "-NOT: pattern specified here");
1139dcc7d48dSMichael Liao     return true;
1140dcc7d48dSMichael Liao   }
1141dcc7d48dSMichael Liao 
1142dcc7d48dSMichael Liao   return false;
1143dcc7d48dSMichael Liao }
1144dcc7d48dSMichael Liao 
11454dabac20SChandler Carruth /// Match "dag strings" and their mixed "not strings".
114691a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
114791a1b2c9SMichael Liao                              std::vector<const Pattern *> &NotStrings,
114891a1b2c9SMichael Liao                              StringMap<StringRef> &VariableTable) const {
114991a1b2c9SMichael Liao   if (DagNotStrings.empty())
115091a1b2c9SMichael Liao     return 0;
115191a1b2c9SMichael Liao 
115291a1b2c9SMichael Liao   size_t LastPos = 0;
115391a1b2c9SMichael Liao   size_t StartPos = LastPos;
115491a1b2c9SMichael Liao 
11558f870499SBenjamin Kramer   for (const Pattern &Pat : DagNotStrings) {
115638820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG ||
115738820972SMatt Arsenault             Pat.getCheckTy() == Check::CheckNot) &&
115891a1b2c9SMichael Liao            "Invalid CHECK-DAG or CHECK-NOT!");
115991a1b2c9SMichael Liao 
116038820972SMatt Arsenault     if (Pat.getCheckTy() == Check::CheckNot) {
116191a1b2c9SMichael Liao       NotStrings.push_back(&Pat);
116291a1b2c9SMichael Liao       continue;
116391a1b2c9SMichael Liao     }
116491a1b2c9SMichael Liao 
116538820972SMatt Arsenault     assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
116691a1b2c9SMichael Liao 
116791a1b2c9SMichael Liao     size_t MatchLen = 0, MatchPos;
116891a1b2c9SMichael Liao 
116991a1b2c9SMichael Liao     // CHECK-DAG always matches from the start.
117091a1b2c9SMichael Liao     StringRef MatchBuffer = Buffer.substr(StartPos);
117191a1b2c9SMichael Liao     MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
117291a1b2c9SMichael Liao     // With a group of CHECK-DAGs, a single mismatching means the match on
117391a1b2c9SMichael Liao     // that group of CHECK-DAGs fails immediately.
117491a1b2c9SMichael Liao     if (MatchPos == StringRef::npos) {
117591a1b2c9SMichael Liao       PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
117691a1b2c9SMichael Liao       return StringRef::npos;
117791a1b2c9SMichael Liao     }
117891a1b2c9SMichael Liao     // Re-calc it as the offset relative to the start of the original string.
117991a1b2c9SMichael Liao     MatchPos += StartPos;
118091a1b2c9SMichael Liao 
118191a1b2c9SMichael Liao     if (!NotStrings.empty()) {
118291a1b2c9SMichael Liao       if (MatchPos < LastPos) {
118391a1b2c9SMichael Liao         // Reordered?
118491a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
118591a1b2c9SMichael Liao                         SourceMgr::DK_Error,
118613df4626SMatt Arsenault                         Prefix + "-DAG: found a match of CHECK-DAG"
118791a1b2c9SMichael Liao                                  " reordering across a CHECK-NOT");
118891a1b2c9SMichael Liao         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
118991a1b2c9SMichael Liao                         SourceMgr::DK_Note,
119013df4626SMatt Arsenault                         Prefix + "-DAG: the farthest match of CHECK-DAG"
119191a1b2c9SMichael Liao                                  " is found here");
119291a1b2c9SMichael Liao         SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
119313df4626SMatt Arsenault                         Prefix + "-NOT: the crossed pattern specified"
119491a1b2c9SMichael Liao                                  " here");
119591a1b2c9SMichael Liao         SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
119613df4626SMatt Arsenault                         Prefix + "-DAG: the reordered pattern specified"
119791a1b2c9SMichael Liao                                  " here");
119891a1b2c9SMichael Liao         return StringRef::npos;
119991a1b2c9SMichael Liao       }
120091a1b2c9SMichael Liao       // All subsequent CHECK-DAGs should be matched from the farthest
120191a1b2c9SMichael Liao       // position of all precedent CHECK-DAGs (including this one.)
120291a1b2c9SMichael Liao       StartPos = LastPos;
120391a1b2c9SMichael Liao       // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
120491a1b2c9SMichael Liao       // CHECK-DAG, verify that there's no 'not' strings occurred in that
120591a1b2c9SMichael Liao       // region.
120691a1b2c9SMichael Liao       StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1207cf708c32STim Northover       if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
120891a1b2c9SMichael Liao         return StringRef::npos;
120991a1b2c9SMichael Liao       // Clear "not strings".
121091a1b2c9SMichael Liao       NotStrings.clear();
121191a1b2c9SMichael Liao     }
121291a1b2c9SMichael Liao 
121391a1b2c9SMichael Liao     // Update the last position with CHECK-DAG matches.
121491a1b2c9SMichael Liao     LastPos = std::max(MatchPos + MatchLen, LastPos);
121591a1b2c9SMichael Liao   }
121691a1b2c9SMichael Liao 
121791a1b2c9SMichael Liao   return LastPos;
121891a1b2c9SMichael Liao }
121991a1b2c9SMichael Liao 
122013df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores.
122113df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) {
122213df4626SMatt Arsenault   Regex Validator("^[a-zA-Z0-9_-]*$");
122313df4626SMatt Arsenault   return Validator.match(CheckPrefix);
122413df4626SMatt Arsenault }
122513df4626SMatt Arsenault 
122613df4626SMatt Arsenault static bool ValidateCheckPrefixes() {
122713df4626SMatt Arsenault   StringSet<> PrefixSet;
122813df4626SMatt Arsenault 
12298f870499SBenjamin Kramer   for (StringRef Prefix : CheckPrefixes) {
123024412b14SEli Bendersky     // Reject empty prefixes.
123124412b14SEli Bendersky     if (Prefix == "")
123224412b14SEli Bendersky       return false;
123324412b14SEli Bendersky 
12340356975cSDavid Blaikie     if (!PrefixSet.insert(Prefix).second)
123513df4626SMatt Arsenault       return false;
123613df4626SMatt Arsenault 
123713df4626SMatt Arsenault     if (!ValidateCheckPrefix(Prefix))
123813df4626SMatt Arsenault       return false;
123913df4626SMatt Arsenault   }
124013df4626SMatt Arsenault 
124113df4626SMatt Arsenault   return true;
124213df4626SMatt Arsenault }
124313df4626SMatt Arsenault 
1244726774cbSChandler Carruth // Combines the check prefixes into a single regex so that we can efficiently
1245726774cbSChandler Carruth // scan for any of the set.
1246726774cbSChandler Carruth //
1247726774cbSChandler Carruth // The semantics are that the longest-match wins which matches our regex
1248726774cbSChandler Carruth // library.
1249726774cbSChandler Carruth static Regex buildCheckPrefixRegex() {
125013df4626SMatt Arsenault   // I don't think there's a way to specify an initial value for cl::list,
125113df4626SMatt Arsenault   // so if nothing was specified, add the default
125213df4626SMatt Arsenault   if (CheckPrefixes.empty())
125313df4626SMatt Arsenault     CheckPrefixes.push_back("CHECK");
1254726774cbSChandler Carruth 
1255726774cbSChandler Carruth   // We already validated the contents of CheckPrefixes so just concatenate
1256726774cbSChandler Carruth   // them as alternatives.
1257726774cbSChandler Carruth   SmallString<32> PrefixRegexStr;
1258726774cbSChandler Carruth   for (StringRef Prefix : CheckPrefixes) {
1259726774cbSChandler Carruth     if (Prefix != CheckPrefixes.front())
1260726774cbSChandler Carruth       PrefixRegexStr.push_back('|');
1261726774cbSChandler Carruth 
1262726774cbSChandler Carruth     PrefixRegexStr.append(Prefix);
1263726774cbSChandler Carruth   }
1264726774cbSChandler Carruth 
1265726774cbSChandler Carruth   return Regex(PrefixRegexStr);
1266c2735158SRui Ueyama }
1267c2735158SRui Ueyama 
12682bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) {
12692bd4f8b6SXinliang David Li   errs() << "FileCheck command line: ";
12702bd4f8b6SXinliang David Li   for (int I = 0; I < argc; I++)
12712bd4f8b6SXinliang David Li     errs() << " " << argv[I];
12722bd4f8b6SXinliang David Li   errs() << "\n";
12732bd4f8b6SXinliang David Li }
12742bd4f8b6SXinliang David Li 
1275f55e72a5SArtem Belevich // Remove local variables from \p VariableTable. Global variables
1276f55e72a5SArtem Belevich // (start with '$') are preserved.
1277f55e72a5SArtem Belevich static void ClearLocalVars(StringMap<StringRef> &VariableTable) {
1278f55e72a5SArtem Belevich   SmallVector<StringRef, 16> LocalVars;
1279f55e72a5SArtem Belevich   for (const auto &Var : VariableTable)
1280f55e72a5SArtem Belevich     if (Var.first()[0] != '$')
1281f55e72a5SArtem Belevich       LocalVars.push_back(Var.first());
1282f55e72a5SArtem Belevich 
1283f55e72a5SArtem Belevich   for (const auto &Var : LocalVars)
1284f55e72a5SArtem Belevich     VariableTable.erase(Var);
1285f55e72a5SArtem Belevich }
1286f55e72a5SArtem Belevich 
128720247900SChandler Carruth /// Check the input to FileCheck provided in the \p Buffer against the \p
128820247900SChandler Carruth /// CheckStrings read from the check file.
128920247900SChandler Carruth ///
129020247900SChandler Carruth /// Returns false if the input fails to satisfy the checks.
129120247900SChandler Carruth bool CheckInput(SourceMgr &SM, StringRef Buffer,
129220247900SChandler Carruth                 ArrayRef<CheckString> CheckStrings) {
129320247900SChandler Carruth   bool ChecksFailed = false;
129420247900SChandler Carruth 
129520247900SChandler Carruth   /// VariableTable - This holds all the current filecheck variables.
129620247900SChandler Carruth   StringMap<StringRef> VariableTable;
129720247900SChandler Carruth 
129820247900SChandler Carruth   unsigned i = 0, j = 0, e = CheckStrings.size();
129920247900SChandler Carruth   while (true) {
130020247900SChandler Carruth     StringRef CheckRegion;
130120247900SChandler Carruth     if (j == e) {
130220247900SChandler Carruth       CheckRegion = Buffer;
130320247900SChandler Carruth     } else {
130420247900SChandler Carruth       const CheckString &CheckLabelStr = CheckStrings[j];
130520247900SChandler Carruth       if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
130620247900SChandler Carruth         ++j;
130720247900SChandler Carruth         continue;
130820247900SChandler Carruth       }
130920247900SChandler Carruth 
131020247900SChandler Carruth       // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
131120247900SChandler Carruth       size_t MatchLabelLen = 0;
1312e8f2fb20SChandler Carruth       size_t MatchLabelPos =
1313e8f2fb20SChandler Carruth           CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, VariableTable);
131420247900SChandler Carruth       if (MatchLabelPos == StringRef::npos)
131520247900SChandler Carruth         // Immediately bail of CHECK-LABEL fails, nothing else we can do.
131620247900SChandler Carruth         return false;
131720247900SChandler Carruth 
131820247900SChandler Carruth       CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
131920247900SChandler Carruth       Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
132020247900SChandler Carruth       ++j;
132120247900SChandler Carruth     }
132220247900SChandler Carruth 
1323f55e72a5SArtem Belevich     if (EnableVarScope)
1324f55e72a5SArtem Belevich       ClearLocalVars(VariableTable);
1325f55e72a5SArtem Belevich 
132620247900SChandler Carruth     for (; i != j; ++i) {
132720247900SChandler Carruth       const CheckString &CheckStr = CheckStrings[i];
132820247900SChandler Carruth 
132920247900SChandler Carruth       // Check each string within the scanned region, including a second check
133020247900SChandler Carruth       // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
133120247900SChandler Carruth       size_t MatchLen = 0;
1332e8f2fb20SChandler Carruth       size_t MatchPos =
1333e8f2fb20SChandler Carruth           CheckStr.Check(SM, CheckRegion, false, MatchLen, VariableTable);
133420247900SChandler Carruth 
133520247900SChandler Carruth       if (MatchPos == StringRef::npos) {
133620247900SChandler Carruth         ChecksFailed = true;
133720247900SChandler Carruth         i = j;
133820247900SChandler Carruth         break;
133920247900SChandler Carruth       }
134020247900SChandler Carruth 
134120247900SChandler Carruth       CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
134220247900SChandler Carruth     }
134320247900SChandler Carruth 
134420247900SChandler Carruth     if (j == e)
134520247900SChandler Carruth       break;
134620247900SChandler Carruth   }
134720247900SChandler Carruth 
134820247900SChandler Carruth   // Success if no checks failed.
134920247900SChandler Carruth   return !ChecksFailed;
135020247900SChandler Carruth }
135120247900SChandler Carruth 
1352ee3c74fbSChris Lattner int main(int argc, char **argv) {
13532ad6d48bSRichard Smith   sys::PrintStackTraceOnErrorSignal(argv[0]);
1354ee3c74fbSChris Lattner   PrettyStackTraceProgram X(argc, argv);
1355ee3c74fbSChris Lattner   cl::ParseCommandLineOptions(argc, argv);
1356ee3c74fbSChris Lattner 
135713df4626SMatt Arsenault   if (!ValidateCheckPrefixes()) {
135813df4626SMatt Arsenault     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
135913df4626SMatt Arsenault               "start with a letter and contain only alphanumeric characters, "
136013df4626SMatt Arsenault               "hyphens and underscores\n";
1361c2735158SRui Ueyama     return 2;
1362c2735158SRui Ueyama   }
1363c2735158SRui Ueyama 
1364726774cbSChandler Carruth   Regex PrefixRE = buildCheckPrefixRegex();
1365726774cbSChandler Carruth   std::string REError;
1366726774cbSChandler Carruth   if (!PrefixRE.isValid(REError)) {
1367726774cbSChandler Carruth     errs() << "Unable to combine check-prefix strings into a prefix regular "
1368726774cbSChandler Carruth               "expression! This is likely a bug in FileCheck's verification of "
1369726774cbSChandler Carruth               "the check-prefix strings. Regular expression parsing failed "
1370726774cbSChandler Carruth               "with the following error: "
1371726774cbSChandler Carruth            << REError << "\n";
1372726774cbSChandler Carruth     return 2;
1373726774cbSChandler Carruth   }
137413df4626SMatt Arsenault 
1375ee3c74fbSChris Lattner   SourceMgr SM;
1376ee3c74fbSChris Lattner 
1377ee3c74fbSChris Lattner   // Read the expected strings from the check file.
137820247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
137920247900SChandler Carruth       MemoryBuffer::getFileOrSTDIN(CheckFilename);
138020247900SChandler Carruth   if (std::error_code EC = CheckFileOrErr.getError()) {
138120247900SChandler Carruth     errs() << "Could not open check file '" << CheckFilename
138220247900SChandler Carruth            << "': " << EC.message() << '\n';
138320247900SChandler Carruth     return 2;
138420247900SChandler Carruth   }
138520247900SChandler Carruth   MemoryBuffer &CheckFile = *CheckFileOrErr.get();
138620247900SChandler Carruth 
138720247900SChandler Carruth   SmallString<4096> CheckFileBuffer;
1388b03c166aSChandler Carruth   StringRef CheckFileText = CanonicalizeFile(CheckFile, CheckFileBuffer);
138920247900SChandler Carruth 
139020247900SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
139120247900SChandler Carruth                             CheckFileText, CheckFile.getBufferIdentifier()),
139220247900SChandler Carruth                         SMLoc());
139320247900SChandler Carruth 
139426cccfe1SChris Lattner   std::vector<CheckString> CheckStrings;
1395726774cbSChandler Carruth   if (ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings))
1396ee3c74fbSChris Lattner     return 2;
1397ee3c74fbSChris Lattner 
1398ee3c74fbSChris Lattner   // Open the file to check and add it to SourceMgr.
139920247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
1400adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(InputFilename);
140120247900SChandler Carruth   if (std::error_code EC = InputFileOrErr.getError()) {
1402adf21f2aSRafael Espindola     errs() << "Could not open input file '" << InputFilename
1403adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
14048e1c6477SEli Bendersky     return 2;
1405ee3c74fbSChris Lattner   }
140620247900SChandler Carruth   MemoryBuffer &InputFile = *InputFileOrErr.get();
14072c3e5cdfSChris Lattner 
140820247900SChandler Carruth   if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
1409b692bed7SChris Lattner     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
14102bd4f8b6SXinliang David Li     DumpCommandLine(argc, argv);
14118e1c6477SEli Bendersky     return 2;
1412b692bed7SChris Lattner   }
1413b692bed7SChris Lattner 
141420247900SChandler Carruth   SmallString<4096> InputFileBuffer;
1415b03c166aSChandler Carruth   StringRef InputFileText = CanonicalizeFile(InputFile, InputFileBuffer);
14162c3e5cdfSChris Lattner 
1417e8f2fb20SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
1418e8f2fb20SChandler Carruth                             InputFileText, InputFile.getBufferIdentifier()),
1419e8f2fb20SChandler Carruth                         SMLoc());
1420ee3c74fbSChris Lattner 
142120247900SChandler Carruth   return CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
1422ee3c74fbSChris Lattner }
1423