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" 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 6546e1fd61SAlexander Richardson static cl::list<std::string> GlobalDefines("D", cl::Prefix, 6646e1fd61SAlexander Richardson cl::desc("Define a variable to be used in capture patterns."), 6746e1fd61SAlexander Richardson cl::value_desc("VAR=VALUE")); 6846e1fd61SAlexander Richardson 691b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput( 701b9f936fSJustin Bogner "allow-empty", cl::init(false), 711b9f936fSJustin Bogner cl::desc("Allow the input file to be empty. This is useful when making\n" 721b9f936fSJustin Bogner "checks that some error message does not occur, for example.")); 731b9f936fSJustin Bogner 7485913ccaSJames Y Knight static cl::opt<bool> MatchFullLines( 7585913ccaSJames Y Knight "match-full-lines", cl::init(false), 7685913ccaSJames Y Knight cl::desc("Require all positive matches to cover an entire input line.\n" 7785913ccaSJames Y Knight "Allows leading and trailing whitespace if --strict-whitespace\n" 7885913ccaSJames Y Knight "is not also passed.")); 7985913ccaSJames Y Knight 80f55e72a5SArtem Belevich static cl::opt<bool> EnableVarScope( 81f55e72a5SArtem Belevich "enable-var-scope", cl::init(false), 82f55e72a5SArtem Belevich cl::desc("Enables scope for regex variables. Variables with names that\n" 83f55e72a5SArtem Belevich "do not start with '$' will be reset at the beginning of\n" 84f55e72a5SArtem Belevich "each CHECK-LABEL block.")); 85f55e72a5SArtem Belevich 8613df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator; 8713df4626SMatt Arsenault 8874d50731SChris Lattner //===----------------------------------------------------------------------===// 8974d50731SChris Lattner // Pattern Handling Code. 9074d50731SChris Lattner //===----------------------------------------------------------------------===// 9174d50731SChris Lattner 9238820972SMatt Arsenault namespace Check { 9338820972SMatt Arsenault enum CheckType { 9438820972SMatt Arsenault CheckNone = 0, 9538820972SMatt Arsenault CheckPlain, 9638820972SMatt Arsenault CheckNext, 9701ac1707SDuncan P. N. Exon Smith CheckSame, 9838820972SMatt Arsenault CheckNot, 9938820972SMatt Arsenault CheckDAG, 10038820972SMatt Arsenault CheckLabel, 1010a4c44bdSChris Lattner 1024dabac20SChandler Carruth /// Indicates the pattern only matches the end of file. This is used for 1034dabac20SChandler Carruth /// trailing CHECK-NOTs. 104a908e7bdSPaul Robinson CheckEOF, 1054dabac20SChandler Carruth 1064dabac20SChandler Carruth /// Marks when parsing found a -NOT check combined with another CHECK suffix. 107a908e7bdSPaul Robinson CheckBadNot 10838820972SMatt Arsenault }; 10938820972SMatt Arsenault } 110eba55822SJakob Stoklund Olesen 11138820972SMatt Arsenault class Pattern { 11238820972SMatt Arsenault SMLoc PatternLoc; 11391a1b2c9SMichael Liao 1144dabac20SChandler Carruth /// A fixed string to match as the pattern or empty if this pattern requires 1154dabac20SChandler Carruth /// a regex match. 116221460e0SChris Lattner StringRef FixedStr; 117b16ab0c4SChris Lattner 1184dabac20SChandler Carruth /// A regex string to match as the pattern or empty if this pattern requires 1194dabac20SChandler Carruth /// a fixed string to match. 120b16ab0c4SChris Lattner std::string RegExStr; 1218879e06dSChris Lattner 1224dabac20SChandler Carruth /// Entries in this vector map to uses of a variable in the pattern, e.g. 1234dabac20SChandler Carruth /// "foo[[bar]]baz". In this case, the RegExStr will contain "foobaz" and 1244dabac20SChandler Carruth /// we'll get an entry in this vector that tells us to insert the value of 1254dabac20SChandler Carruth /// bar at offset 3. 1268879e06dSChris Lattner std::vector<std::pair<StringRef, unsigned>> VariableUses; 1278879e06dSChris Lattner 1284dabac20SChandler Carruth /// Maps definitions of variables to their parenthesized capture numbers. 1294dabac20SChandler Carruth /// 1304dabac20SChandler Carruth /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 1314dabac20SChandler Carruth /// 1. 132e8b8f1bcSEli Bendersky std::map<StringRef, unsigned> VariableDefs; 1338879e06dSChris Lattner 134d1e020f7SSaleem Abdulrasool Check::CheckType CheckTy; 1353b40b445SChris Lattner 1364dabac20SChandler Carruth /// Contains the number of line this pattern is in. 137d1e020f7SSaleem Abdulrasool unsigned LineNumber; 138d1e020f7SSaleem Abdulrasool 139d1e020f7SSaleem Abdulrasool public: 140d1e020f7SSaleem Abdulrasool explicit Pattern(Check::CheckType Ty) : CheckTy(Ty) {} 14174d50731SChris Lattner 1424dabac20SChandler Carruth /// Returns the location in source code. 1430b707eb8SMichael Liao SMLoc getLoc() const { return PatternLoc; } 1440b707eb8SMichael Liao 145e8f2fb20SChandler Carruth bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, 14613df4626SMatt Arsenault unsigned LineNumber); 1478879e06dSChris Lattner size_t Match(StringRef Buffer, size_t &MatchLen, 1488879e06dSChris Lattner StringMap<StringRef> &VariableTable) const; 149e0ef65abSDaniel Dunbar void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 150e0ef65abSDaniel Dunbar const StringMap<StringRef> &VariableTable) const; 151e0ef65abSDaniel Dunbar 152e8f2fb20SChandler Carruth bool hasVariable() const { 153e8f2fb20SChandler Carruth return !(VariableUses.empty() && VariableDefs.empty()); 154e8f2fb20SChandler Carruth } 155f8bd2e5bSStephen Lin 15638820972SMatt Arsenault Check::CheckType getCheckTy() const { return CheckTy; } 15791a1b2c9SMichael Liao 158b16ab0c4SChris Lattner private: 159e8b8f1bcSEli Bendersky bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); 160e8b8f1bcSEli Bendersky void AddBackrefToRegEx(unsigned BackrefNum); 161e8f2fb20SChandler Carruth unsigned 162e8f2fb20SChandler Carruth ComputeMatchDistance(StringRef Buffer, 163fd29d886SDaniel Dunbar const StringMap<StringRef> &VariableTable) const; 16492987fb3SAlexander Kornienko bool EvaluateExpression(StringRef Expr, std::string &Value) const; 16581e5cd9eSAdrian Prantl size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); 1663b40b445SChris Lattner }; 1673b40b445SChris Lattner 1684dabac20SChandler Carruth /// Parses the given string into the Pattern. 1694dabac20SChandler Carruth /// 1704dabac20SChandler Carruth /// \p Prefix provides which prefix is being matched, \p SM provides the 1714dabac20SChandler Carruth /// SourceMgr used for error reports, and \p LineNumber is the line number in 1724dabac20SChandler Carruth /// the input file from which the pattern string was read. Returns true in 1734dabac20SChandler Carruth /// case of an error, false otherwise. 174e8f2fb20SChandler Carruth bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix, 175e8f2fb20SChandler Carruth SourceMgr &SM, unsigned LineNumber) { 17685913ccaSJames Y Knight bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot; 17785913ccaSJames Y Knight 17892987fb3SAlexander Kornienko this->LineNumber = LineNumber; 1790a4c44bdSChris Lattner PatternLoc = SMLoc::getFromPointer(PatternStr.data()); 1800a4c44bdSChris Lattner 1811714676aSTom de Vries if (!(NoCanonicalizeWhiteSpace && MatchFullLines)) 18274d50731SChris Lattner // Ignore trailing whitespace. 18374d50731SChris Lattner while (!PatternStr.empty() && 18474d50731SChris Lattner (PatternStr.back() == ' ' || PatternStr.back() == '\t')) 18574d50731SChris Lattner PatternStr = PatternStr.substr(0, PatternStr.size() - 1); 18674d50731SChris Lattner 18774d50731SChris Lattner // Check that there is something on the line. 18874d50731SChris Lattner if (PatternStr.empty()) { 18903b80a40SChris Lattner SM.PrintMessage(PatternLoc, SourceMgr::DK_Error, 190e8f2fb20SChandler Carruth "found empty check string with prefix '" + Prefix + ":'"); 19174d50731SChris Lattner return true; 19274d50731SChris Lattner } 19374d50731SChris Lattner 194221460e0SChris Lattner // Check to see if this is a fixed string, or if it has regex pieces. 19585913ccaSJames Y Knight if (!MatchFullLinesHere && 19685913ccaSJames Y Knight (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && 19785913ccaSJames Y Knight PatternStr.find("[[") == StringRef::npos))) { 198221460e0SChris Lattner FixedStr = PatternStr; 199221460e0SChris Lattner return false; 200221460e0SChris Lattner } 201221460e0SChris Lattner 20285913ccaSJames Y Knight if (MatchFullLinesHere) { 20385913ccaSJames Y Knight RegExStr += '^'; 20485913ccaSJames Y Knight if (!NoCanonicalizeWhiteSpace) 20585913ccaSJames Y Knight RegExStr += " *"; 20685913ccaSJames Y Knight } 20785913ccaSJames Y Knight 2088879e06dSChris Lattner // Paren value #0 is for the fully matched string. Any new parenthesized 20953e0679dSChris Lattner // values add from there. 2108879e06dSChris Lattner unsigned CurParen = 1; 2118879e06dSChris Lattner 212b16ab0c4SChris Lattner // Otherwise, there is at least one regex piece. Build up the regex pattern 213b16ab0c4SChris Lattner // by escaping scary characters in fixed strings, building up one big regex. 214f08d2db9SChris Lattner while (!PatternStr.empty()) { 2158879e06dSChris Lattner // RegEx matches. 21653e0679dSChris Lattner if (PatternStr.startswith("{{")) { 21743d50d4aSEli Bendersky // This is the start of a regex match. Scan for the }}. 218f08d2db9SChris Lattner size_t End = PatternStr.find("}}"); 219f08d2db9SChris Lattner if (End == StringRef::npos) { 220f08d2db9SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 22103b80a40SChris Lattner SourceMgr::DK_Error, 22203b80a40SChris Lattner "found start of regex string with no end '}}'"); 223f08d2db9SChris Lattner return true; 224f08d2db9SChris Lattner } 225f08d2db9SChris Lattner 226e53c95f1SChris Lattner // Enclose {{}} patterns in parens just like [[]] even though we're not 227e53c95f1SChris Lattner // capturing the result for any purpose. This is required in case the 228e53c95f1SChris Lattner // expression contains an alternation like: CHECK: abc{{x|z}}def. We 229e53c95f1SChris Lattner // want this to turn into: "abc(x|z)def" not "abcx|zdef". 230e53c95f1SChris Lattner RegExStr += '('; 231e53c95f1SChris Lattner ++CurParen; 232e53c95f1SChris Lattner 2338879e06dSChris Lattner if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM)) 2348879e06dSChris Lattner return true; 235e53c95f1SChris Lattner RegExStr += ')'; 23653e0679dSChris Lattner 2378879e06dSChris Lattner PatternStr = PatternStr.substr(End + 2); 2388879e06dSChris Lattner continue; 2398879e06dSChris Lattner } 2408879e06dSChris Lattner 2418879e06dSChris Lattner // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* 2428879e06dSChris Lattner // (or some other regex) and assigns it to the FileCheck variable 'foo'. The 2438879e06dSChris Lattner // second form is [[foo]] which is a reference to foo. The variable name 24457cb733bSDaniel Dunbar // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject 2458879e06dSChris Lattner // it. This is to catch some common errors. 24653e0679dSChris Lattner if (PatternStr.startswith("[[")) { 247061d2baaSEli Bendersky // Find the closing bracket pair ending the match. End is going to be an 248061d2baaSEli Bendersky // offset relative to the beginning of the match string. 24981e5cd9eSAdrian Prantl size_t End = FindRegexVarEnd(PatternStr.substr(2), SM); 250061d2baaSEli Bendersky 2518879e06dSChris Lattner if (End == StringRef::npos) { 2528879e06dSChris Lattner SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 25303b80a40SChris Lattner SourceMgr::DK_Error, 25403b80a40SChris Lattner "invalid named regex reference, no ]] found"); 255f08d2db9SChris Lattner return true; 256f08d2db9SChris Lattner } 257f08d2db9SChris Lattner 258061d2baaSEli Bendersky StringRef MatchStr = PatternStr.substr(2, End); 259061d2baaSEli Bendersky PatternStr = PatternStr.substr(End + 4); 2608879e06dSChris Lattner 2618879e06dSChris Lattner // Get the regex name (e.g. "foo"). 2628879e06dSChris Lattner size_t NameEnd = MatchStr.find(':'); 2638879e06dSChris Lattner StringRef Name = MatchStr.substr(0, NameEnd); 2648879e06dSChris Lattner 2658879e06dSChris Lattner if (Name.empty()) { 26603b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 26703b80a40SChris Lattner "invalid name in named regex: empty name"); 2688879e06dSChris Lattner return true; 2698879e06dSChris Lattner } 2708879e06dSChris Lattner 27192987fb3SAlexander Kornienko // Verify that the name/expression is well formed. FileCheck currently 27292987fb3SAlexander Kornienko // supports @LINE, @LINE+number, @LINE-number expressions. The check here 27392987fb3SAlexander Kornienko // is relaxed, more strict check is performed in \c EvaluateExpression. 27492987fb3SAlexander Kornienko bool IsExpression = false; 27592987fb3SAlexander Kornienko for (unsigned i = 0, e = Name.size(); i != e; ++i) { 276f55e72a5SArtem Belevich if (i == 0) { 277f55e72a5SArtem Belevich if (Name[i] == '$') // Global vars start with '$' 278f55e72a5SArtem Belevich continue; 279f55e72a5SArtem Belevich if (Name[i] == '@') { 28092987fb3SAlexander Kornienko if (NameEnd != StringRef::npos) { 28192987fb3SAlexander Kornienko SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 28292987fb3SAlexander Kornienko SourceMgr::DK_Error, 28392987fb3SAlexander Kornienko "invalid name in named regex definition"); 28492987fb3SAlexander Kornienko return true; 28592987fb3SAlexander Kornienko } 28692987fb3SAlexander Kornienko IsExpression = true; 28792987fb3SAlexander Kornienko continue; 28892987fb3SAlexander Kornienko } 289f55e72a5SArtem Belevich } 29092987fb3SAlexander Kornienko if (Name[i] != '_' && !isalnum(Name[i]) && 29192987fb3SAlexander Kornienko (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) { 2928879e06dSChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data() + i), 29303b80a40SChris Lattner SourceMgr::DK_Error, "invalid name in named regex"); 2948879e06dSChris Lattner return true; 2958879e06dSChris Lattner } 29692987fb3SAlexander Kornienko } 2978879e06dSChris Lattner 2988879e06dSChris Lattner // Name can't start with a digit. 29983c74e9fSGuy Benyei if (isdigit(static_cast<unsigned char>(Name[0]))) { 30003b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 30103b80a40SChris Lattner "invalid name in named regex"); 3028879e06dSChris Lattner return true; 3038879e06dSChris Lattner } 3048879e06dSChris Lattner 3058879e06dSChris Lattner // Handle [[foo]]. 3068879e06dSChris Lattner if (NameEnd == StringRef::npos) { 307e8b8f1bcSEli Bendersky // Handle variables that were defined earlier on the same line by 308e8b8f1bcSEli Bendersky // emitting a backreference. 309e8b8f1bcSEli Bendersky if (VariableDefs.find(Name) != VariableDefs.end()) { 310e8b8f1bcSEli Bendersky unsigned VarParenNum = VariableDefs[Name]; 311e8b8f1bcSEli Bendersky if (VarParenNum < 1 || VarParenNum > 9) { 312e8b8f1bcSEli Bendersky SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 313e8b8f1bcSEli Bendersky SourceMgr::DK_Error, 314e8b8f1bcSEli Bendersky "Can't back-reference more than 9 variables"); 315e8b8f1bcSEli Bendersky return true; 316e8b8f1bcSEli Bendersky } 317e8b8f1bcSEli Bendersky AddBackrefToRegEx(VarParenNum); 318e8b8f1bcSEli Bendersky } else { 3198879e06dSChris Lattner VariableUses.push_back(std::make_pair(Name, RegExStr.size())); 320e8b8f1bcSEli Bendersky } 3218879e06dSChris Lattner continue; 3228879e06dSChris Lattner } 3238879e06dSChris Lattner 3248879e06dSChris Lattner // Handle [[foo:.*]]. 325e8b8f1bcSEli Bendersky VariableDefs[Name] = CurParen; 3268879e06dSChris Lattner RegExStr += '('; 3278879e06dSChris Lattner ++CurParen; 3288879e06dSChris Lattner 3298879e06dSChris Lattner if (AddRegExToRegEx(MatchStr.substr(NameEnd + 1), CurParen, SM)) 3308879e06dSChris Lattner return true; 3318879e06dSChris Lattner 3328879e06dSChris Lattner RegExStr += ')'; 3338879e06dSChris Lattner } 3348879e06dSChris Lattner 3358879e06dSChris Lattner // Handle fixed string matches. 3368879e06dSChris Lattner // Find the end, which is the start of the next regex. 3378879e06dSChris Lattner size_t FixedMatchEnd = PatternStr.find("{{"); 3388879e06dSChris Lattner FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); 3396f4f77b7SHans Wennborg RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd)); 3408879e06dSChris Lattner PatternStr = PatternStr.substr(FixedMatchEnd); 341f08d2db9SChris Lattner } 342f08d2db9SChris Lattner 34385913ccaSJames Y Knight if (MatchFullLinesHere) { 34485913ccaSJames Y Knight if (!NoCanonicalizeWhiteSpace) 34585913ccaSJames Y Knight RegExStr += " *"; 34685913ccaSJames Y Knight RegExStr += '$'; 34785913ccaSJames Y Knight } 34885913ccaSJames Y Knight 34974d50731SChris Lattner return false; 35074d50731SChris Lattner } 35174d50731SChris Lattner 352e8f2fb20SChandler Carruth bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) { 353e8b8f1bcSEli Bendersky Regex R(RS); 3548879e06dSChris Lattner std::string Error; 3558879e06dSChris Lattner if (!R.isValid(Error)) { 356e8b8f1bcSEli Bendersky SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error, 35703b80a40SChris Lattner "invalid regex: " + Error); 3588879e06dSChris Lattner return true; 3598879e06dSChris Lattner } 3608879e06dSChris Lattner 361e8b8f1bcSEli Bendersky RegExStr += RS.str(); 3628879e06dSChris Lattner CurParen += R.getNumMatches(); 3638879e06dSChris Lattner return false; 3648879e06dSChris Lattner } 365b16ab0c4SChris Lattner 366e8b8f1bcSEli Bendersky void Pattern::AddBackrefToRegEx(unsigned BackrefNum) { 367e8b8f1bcSEli Bendersky assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number"); 368e8f2fb20SChandler Carruth std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum); 369e8b8f1bcSEli Bendersky RegExStr += Backref; 370e8b8f1bcSEli Bendersky } 371e8b8f1bcSEli Bendersky 3724dabac20SChandler Carruth /// Evaluates expression and stores the result to \p Value. 3734dabac20SChandler Carruth /// 3744dabac20SChandler Carruth /// Returns true on success and false when the expression has invalid syntax. 37592987fb3SAlexander Kornienko bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const { 37692987fb3SAlexander Kornienko // The only supported expression is @LINE([\+-]\d+)? 37792987fb3SAlexander Kornienko if (!Expr.startswith("@LINE")) 37892987fb3SAlexander Kornienko return false; 37992987fb3SAlexander Kornienko Expr = Expr.substr(StringRef("@LINE").size()); 38092987fb3SAlexander Kornienko int Offset = 0; 38192987fb3SAlexander Kornienko if (!Expr.empty()) { 38292987fb3SAlexander Kornienko if (Expr[0] == '+') 38392987fb3SAlexander Kornienko Expr = Expr.substr(1); 38492987fb3SAlexander Kornienko else if (Expr[0] != '-') 38592987fb3SAlexander Kornienko return false; 38692987fb3SAlexander Kornienko if (Expr.getAsInteger(10, Offset)) 38792987fb3SAlexander Kornienko return false; 38892987fb3SAlexander Kornienko } 38992987fb3SAlexander Kornienko Value = llvm::itostr(LineNumber + Offset); 39092987fb3SAlexander Kornienko return true; 39192987fb3SAlexander Kornienko } 39292987fb3SAlexander Kornienko 3934dabac20SChandler Carruth /// Matches the pattern string against the input buffer \p Buffer 3944dabac20SChandler Carruth /// 3954dabac20SChandler Carruth /// This returns the position that is matched or npos if there is no match. If 3964dabac20SChandler Carruth /// there is a match, the size of the matched string is returned in \p 3974dabac20SChandler Carruth /// MatchLen. 3984dabac20SChandler Carruth /// 3994dabac20SChandler Carruth /// The \p VariableTable StringMap provides the current values of filecheck 4004dabac20SChandler Carruth /// variables and is updated if this match defines new values. 4018879e06dSChris Lattner size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, 4028879e06dSChris Lattner StringMap<StringRef> &VariableTable) const { 403eba55822SJakob Stoklund Olesen // If this is the EOF pattern, match it immediately. 40438820972SMatt Arsenault if (CheckTy == Check::CheckEOF) { 405eba55822SJakob Stoklund Olesen MatchLen = 0; 406eba55822SJakob Stoklund Olesen return Buffer.size(); 407eba55822SJakob Stoklund Olesen } 408eba55822SJakob Stoklund Olesen 409221460e0SChris Lattner // If this is a fixed string pattern, just match it now. 410221460e0SChris Lattner if (!FixedStr.empty()) { 411221460e0SChris Lattner MatchLen = FixedStr.size(); 412221460e0SChris Lattner return Buffer.find(FixedStr); 413221460e0SChris Lattner } 414221460e0SChris Lattner 415b16ab0c4SChris Lattner // Regex match. 4168879e06dSChris Lattner 4178879e06dSChris Lattner // If there are variable uses, we need to create a temporary string with the 4188879e06dSChris Lattner // actual value. 4198879e06dSChris Lattner StringRef RegExToMatch = RegExStr; 4208879e06dSChris Lattner std::string TmpStr; 4218879e06dSChris Lattner if (!VariableUses.empty()) { 4228879e06dSChris Lattner TmpStr = RegExStr; 4238879e06dSChris Lattner 4248879e06dSChris Lattner unsigned InsertOffset = 0; 4258f870499SBenjamin Kramer for (const auto &VariableUse : VariableUses) { 42692987fb3SAlexander Kornienko std::string Value; 42792987fb3SAlexander Kornienko 4288f870499SBenjamin Kramer if (VariableUse.first[0] == '@') { 4298f870499SBenjamin Kramer if (!EvaluateExpression(VariableUse.first, Value)) 43092987fb3SAlexander Kornienko return StringRef::npos; 43192987fb3SAlexander Kornienko } else { 432e0ef65abSDaniel Dunbar StringMap<StringRef>::iterator it = 4338f870499SBenjamin Kramer VariableTable.find(VariableUse.first); 434e0ef65abSDaniel Dunbar // If the variable is undefined, return an error. 435e0ef65abSDaniel Dunbar if (it == VariableTable.end()) 436e0ef65abSDaniel Dunbar return StringRef::npos; 437e0ef65abSDaniel Dunbar 4386f4f77b7SHans Wennborg // Look up the value and escape it so that we can put it into the regex. 4396f4f77b7SHans Wennborg Value += Regex::escape(it->second); 44092987fb3SAlexander Kornienko } 4418879e06dSChris Lattner 4428879e06dSChris Lattner // Plop it into the regex at the adjusted offset. 4438f870499SBenjamin Kramer TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset, 4448879e06dSChris Lattner Value.begin(), Value.end()); 4458879e06dSChris Lattner InsertOffset += Value.size(); 4468879e06dSChris Lattner } 4478879e06dSChris Lattner 4488879e06dSChris Lattner // Match the newly constructed regex. 4498879e06dSChris Lattner RegExToMatch = TmpStr; 4508879e06dSChris Lattner } 4518879e06dSChris Lattner 452b16ab0c4SChris Lattner SmallVector<StringRef, 4> MatchInfo; 4538879e06dSChris Lattner if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo)) 454f08d2db9SChris Lattner return StringRef::npos; 455b16ab0c4SChris Lattner 456b16ab0c4SChris Lattner // Successful regex match. 457b16ab0c4SChris Lattner assert(!MatchInfo.empty() && "Didn't get any match"); 458b16ab0c4SChris Lattner StringRef FullMatch = MatchInfo[0]; 459b16ab0c4SChris Lattner 4608879e06dSChris Lattner // If this defines any variables, remember their values. 4618f870499SBenjamin Kramer for (const auto &VariableDef : VariableDefs) { 4628f870499SBenjamin Kramer assert(VariableDef.second < MatchInfo.size() && "Internal paren error"); 4638f870499SBenjamin Kramer VariableTable[VariableDef.first] = MatchInfo[VariableDef.second]; 4640a4c44bdSChris Lattner } 4650a4c44bdSChris Lattner 466b16ab0c4SChris Lattner MatchLen = FullMatch.size(); 467b16ab0c4SChris Lattner return FullMatch.data() - Buffer.data(); 468f08d2db9SChris Lattner } 469f08d2db9SChris Lattner 4704dabac20SChandler Carruth 4714dabac20SChandler Carruth /// Computes an arbitrary estimate for the quality of matching this pattern at 4724dabac20SChandler Carruth /// the start of \p Buffer; a distance of zero should correspond to a perfect 4734dabac20SChandler Carruth /// match. 474e8f2fb20SChandler Carruth unsigned 475e8f2fb20SChandler Carruth Pattern::ComputeMatchDistance(StringRef Buffer, 476fd29d886SDaniel Dunbar const StringMap<StringRef> &VariableTable) const { 477fd29d886SDaniel Dunbar // Just compute the number of matching characters. For regular expressions, we 478fd29d886SDaniel Dunbar // just compare against the regex itself and hope for the best. 479fd29d886SDaniel Dunbar // 480fd29d886SDaniel Dunbar // FIXME: One easy improvement here is have the regex lib generate a single 481fd29d886SDaniel Dunbar // example regular expression which matches, and use that as the example 482fd29d886SDaniel Dunbar // string. 483fd29d886SDaniel Dunbar StringRef ExampleString(FixedStr); 484fd29d886SDaniel Dunbar if (ExampleString.empty()) 485fd29d886SDaniel Dunbar ExampleString = RegExStr; 486fd29d886SDaniel Dunbar 487e9aa36c8SDaniel Dunbar // Only compare up to the first line in the buffer, or the string size. 488e9aa36c8SDaniel Dunbar StringRef BufferPrefix = Buffer.substr(0, ExampleString.size()); 489e9aa36c8SDaniel Dunbar BufferPrefix = BufferPrefix.split('\n').first; 490e9aa36c8SDaniel Dunbar return BufferPrefix.edit_distance(ExampleString); 491fd29d886SDaniel Dunbar } 492fd29d886SDaniel Dunbar 4934dabac20SChandler Carruth /// Prints additional information about a failure to match involving this 4944dabac20SChandler Carruth /// pattern. 495e8f2fb20SChandler Carruth void Pattern::PrintFailureInfo( 496e8f2fb20SChandler Carruth const SourceMgr &SM, StringRef Buffer, 497e0ef65abSDaniel Dunbar const StringMap<StringRef> &VariableTable) const { 498e0ef65abSDaniel Dunbar // If this was a regular expression using variables, print the current 499e0ef65abSDaniel Dunbar // variable values. 500e0ef65abSDaniel Dunbar if (!VariableUses.empty()) { 5018f870499SBenjamin Kramer for (const auto &VariableUse : VariableUses) { 502e69170a1SAlp Toker SmallString<256> Msg; 503e69170a1SAlp Toker raw_svector_ostream OS(Msg); 5048f870499SBenjamin Kramer StringRef Var = VariableUse.first; 50592987fb3SAlexander Kornienko if (Var[0] == '@') { 50692987fb3SAlexander Kornienko std::string Value; 50792987fb3SAlexander Kornienko if (EvaluateExpression(Var, Value)) { 50892987fb3SAlexander Kornienko OS << "with expression \""; 50992987fb3SAlexander Kornienko OS.write_escaped(Var) << "\" equal to \""; 51092987fb3SAlexander Kornienko OS.write_escaped(Value) << "\""; 51192987fb3SAlexander Kornienko } else { 51292987fb3SAlexander Kornienko OS << "uses incorrect expression \""; 51392987fb3SAlexander Kornienko OS.write_escaped(Var) << "\""; 51492987fb3SAlexander Kornienko } 51592987fb3SAlexander Kornienko } else { 51692987fb3SAlexander Kornienko StringMap<StringRef>::const_iterator it = VariableTable.find(Var); 517e0ef65abSDaniel Dunbar 518e0ef65abSDaniel Dunbar // Check for undefined variable references. 519e0ef65abSDaniel Dunbar if (it == VariableTable.end()) { 520e0ef65abSDaniel Dunbar OS << "uses undefined variable \""; 52192987fb3SAlexander Kornienko OS.write_escaped(Var) << "\""; 522e0ef65abSDaniel Dunbar } else { 523e0ef65abSDaniel Dunbar OS << "with variable \""; 524e0ef65abSDaniel Dunbar OS.write_escaped(Var) << "\" equal to \""; 525e0ef65abSDaniel Dunbar OS.write_escaped(it->second) << "\""; 526e0ef65abSDaniel Dunbar } 52792987fb3SAlexander Kornienko } 528e0ef65abSDaniel Dunbar 52903b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 53003b80a40SChris Lattner OS.str()); 531e0ef65abSDaniel Dunbar } 532e0ef65abSDaniel Dunbar } 533fd29d886SDaniel Dunbar 534fd29d886SDaniel Dunbar // Attempt to find the closest/best fuzzy match. Usually an error happens 535fd29d886SDaniel Dunbar // because some string in the output didn't exactly match. In these cases, we 536fd29d886SDaniel Dunbar // would like to show the user a best guess at what "should have" matched, to 537fd29d886SDaniel Dunbar // save them having to actually check the input manually. 538fd29d886SDaniel Dunbar size_t NumLinesForward = 0; 539fd29d886SDaniel Dunbar size_t Best = StringRef::npos; 540fd29d886SDaniel Dunbar double BestQuality = 0; 541fd29d886SDaniel Dunbar 542fd29d886SDaniel Dunbar // Use an arbitrary 4k limit on how far we will search. 5432bf486ebSDan Gohman for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { 544fd29d886SDaniel Dunbar if (Buffer[i] == '\n') 545fd29d886SDaniel Dunbar ++NumLinesForward; 546fd29d886SDaniel Dunbar 547df22bbf7SDan Gohman // Patterns have leading whitespace stripped, so skip whitespace when 548df22bbf7SDan Gohman // looking for something which looks like a pattern. 549df22bbf7SDan Gohman if (Buffer[i] == ' ' || Buffer[i] == '\t') 550df22bbf7SDan Gohman continue; 551df22bbf7SDan Gohman 552fd29d886SDaniel Dunbar // Compute the "quality" of this match as an arbitrary combination of the 553fd29d886SDaniel Dunbar // match distance and the number of lines skipped to get to this match. 554fd29d886SDaniel Dunbar unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); 555fd29d886SDaniel Dunbar double Quality = Distance + (NumLinesForward / 100.); 556fd29d886SDaniel Dunbar 557fd29d886SDaniel Dunbar if (Quality < BestQuality || Best == StringRef::npos) { 558fd29d886SDaniel Dunbar Best = i; 559fd29d886SDaniel Dunbar BestQuality = Quality; 560fd29d886SDaniel Dunbar } 561fd29d886SDaniel Dunbar } 562fd29d886SDaniel Dunbar 563fd29d886SDaniel Dunbar // Print the "possible intended match here" line if we found something 564c069cc8eSDaniel Dunbar // reasonable and not equal to what we showed in the "scanning from here" 565c069cc8eSDaniel Dunbar // line. 566c069cc8eSDaniel Dunbar if (Best && Best != StringRef::npos && BestQuality < 50) { 567fd29d886SDaniel Dunbar SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), 56803b80a40SChris Lattner SourceMgr::DK_Note, "possible intended match here"); 569fd29d886SDaniel Dunbar 570fd29d886SDaniel Dunbar // FIXME: If we wanted to be really friendly we would show why the match 571fd29d886SDaniel Dunbar // failed, as it can be hard to spot simple one character differences. 572fd29d886SDaniel Dunbar } 573e0ef65abSDaniel Dunbar } 57474d50731SChris Lattner 5754dabac20SChandler Carruth /// Finds the closing sequence of a regex variable usage or definition. 5764dabac20SChandler Carruth /// 5774dabac20SChandler Carruth /// \p Str has to point in the beginning of the definition (right after the 5784dabac20SChandler Carruth /// opening sequence). Returns the offset of the closing sequence within Str, 5794dabac20SChandler Carruth /// or npos if it was not found. 58081e5cd9eSAdrian Prantl size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { 581061d2baaSEli Bendersky // Offset keeps track of the current offset within the input Str 582061d2baaSEli Bendersky size_t Offset = 0; 583061d2baaSEli Bendersky // [...] Nesting depth 584061d2baaSEli Bendersky size_t BracketDepth = 0; 585061d2baaSEli Bendersky 586061d2baaSEli Bendersky while (!Str.empty()) { 587061d2baaSEli Bendersky if (Str.startswith("]]") && BracketDepth == 0) 588061d2baaSEli Bendersky return Offset; 589061d2baaSEli Bendersky if (Str[0] == '\\') { 590061d2baaSEli Bendersky // Backslash escapes the next char within regexes, so skip them both. 591061d2baaSEli Bendersky Str = Str.substr(2); 592061d2baaSEli Bendersky Offset += 2; 593061d2baaSEli Bendersky } else { 594061d2baaSEli Bendersky switch (Str[0]) { 595061d2baaSEli Bendersky default: 596061d2baaSEli Bendersky break; 597061d2baaSEli Bendersky case '[': 598061d2baaSEli Bendersky BracketDepth++; 599061d2baaSEli Bendersky break; 600061d2baaSEli Bendersky case ']': 60181e5cd9eSAdrian Prantl if (BracketDepth == 0) { 60281e5cd9eSAdrian Prantl SM.PrintMessage(SMLoc::getFromPointer(Str.data()), 60381e5cd9eSAdrian Prantl SourceMgr::DK_Error, 60481e5cd9eSAdrian Prantl "missing closing \"]\" for regex variable"); 60581e5cd9eSAdrian Prantl exit(1); 60681e5cd9eSAdrian Prantl } 607061d2baaSEli Bendersky BracketDepth--; 608061d2baaSEli Bendersky break; 609061d2baaSEli Bendersky } 610061d2baaSEli Bendersky Str = Str.substr(1); 611061d2baaSEli Bendersky Offset++; 612061d2baaSEli Bendersky } 613061d2baaSEli Bendersky } 614061d2baaSEli Bendersky 615061d2baaSEli Bendersky return StringRef::npos; 616061d2baaSEli Bendersky } 617061d2baaSEli Bendersky 61874d50731SChris Lattner //===----------------------------------------------------------------------===// 61974d50731SChris Lattner // Check Strings. 62074d50731SChris Lattner //===----------------------------------------------------------------------===// 6213b40b445SChris Lattner 6224dabac20SChandler Carruth /// A check that we found in the input file. 6233b40b445SChris Lattner struct CheckString { 6244dabac20SChandler Carruth /// The pattern to match. 6253b40b445SChris Lattner Pattern Pat; 62626cccfe1SChris Lattner 6274dabac20SChandler Carruth /// Which prefix name this check matched. 62813df4626SMatt Arsenault StringRef Prefix; 62913df4626SMatt Arsenault 6304dabac20SChandler Carruth /// The location in the match file that the check string was specified. 63126cccfe1SChris Lattner SMLoc Loc; 63226cccfe1SChris Lattner 6334dabac20SChandler Carruth /// All of the strings that are disallowed from occurring between this match 6344dabac20SChandler Carruth /// string and the previous one (or start of file). 63591a1b2c9SMichael Liao std::vector<Pattern> DagNotStrings; 636236d2d5eSChris Lattner 63785913ccaSJames Y Knight CheckString(const Pattern &P, StringRef S, SMLoc L) 63885913ccaSJames Y Knight : Pat(P), Prefix(S), Loc(L) {} 639dcc7d48dSMichael Liao 640e93a3a08SStephen Lin size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, 641f8bd2e5bSStephen Lin size_t &MatchLen, StringMap<StringRef> &VariableTable) const; 642dcc7d48dSMichael Liao 643dcc7d48dSMichael Liao bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; 64401ac1707SDuncan P. N. Exon Smith bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; 645dcc7d48dSMichael Liao bool CheckNot(const SourceMgr &SM, StringRef Buffer, 64691a1b2c9SMichael Liao const std::vector<const Pattern *> &NotStrings, 64791a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) const; 64891a1b2c9SMichael Liao size_t CheckDag(const SourceMgr &SM, StringRef Buffer, 64991a1b2c9SMichael Liao std::vector<const Pattern *> &NotStrings, 650dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const; 65126cccfe1SChris Lattner }; 65226cccfe1SChris Lattner 65320247900SChandler Carruth /// Canonicalize whitespaces in the file. Line endings are replaced with 65420247900SChandler Carruth /// UNIX-style '\n'. 655b03c166aSChandler Carruth static StringRef CanonicalizeFile(MemoryBuffer &MB, 65620247900SChandler Carruth SmallVectorImpl<char> &OutputBuffer) { 65720247900SChandler Carruth OutputBuffer.reserve(MB.getBufferSize()); 658a2f8fc5aSChris Lattner 65920247900SChandler Carruth for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd(); 660a2f8fc5aSChris Lattner Ptr != End; ++Ptr) { 661fd781bf0SNAKAMURA Takumi // Eliminate trailing dosish \r. 662fd781bf0SNAKAMURA Takumi if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { 663fd781bf0SNAKAMURA Takumi continue; 664fd781bf0SNAKAMURA Takumi } 665fd781bf0SNAKAMURA Takumi 6665ea04c38SGuy Benyei // If current char is not a horizontal whitespace or if horizontal 6675ea04c38SGuy Benyei // whitespace canonicalization is disabled, dump it to output as is. 668b03c166aSChandler Carruth if (NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) { 66920247900SChandler Carruth OutputBuffer.push_back(*Ptr); 670a2f8fc5aSChris Lattner continue; 671a2f8fc5aSChris Lattner } 672a2f8fc5aSChris Lattner 673a2f8fc5aSChris Lattner // Otherwise, add one space and advance over neighboring space. 67420247900SChandler Carruth OutputBuffer.push_back(' '); 675e8f2fb20SChandler Carruth while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t')) 676a2f8fc5aSChris Lattner ++Ptr; 677a2f8fc5aSChris Lattner } 678a2f8fc5aSChris Lattner 67920247900SChandler Carruth // Add a null byte and then return all but that byte. 68020247900SChandler Carruth OutputBuffer.push_back('\0'); 68120247900SChandler Carruth return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1); 682a2f8fc5aSChris Lattner } 683a2f8fc5aSChris Lattner 68438820972SMatt Arsenault static bool IsPartOfWord(char c) { 68538820972SMatt Arsenault return (isalnum(c) || c == '-' || c == '_'); 68638820972SMatt Arsenault } 68738820972SMatt Arsenault 68813df4626SMatt Arsenault // Get the size of the prefix extension. 68913df4626SMatt Arsenault static size_t CheckTypeSize(Check::CheckType Ty) { 69013df4626SMatt Arsenault switch (Ty) { 69113df4626SMatt Arsenault case Check::CheckNone: 692a908e7bdSPaul Robinson case Check::CheckBadNot: 69313df4626SMatt Arsenault return 0; 69413df4626SMatt Arsenault 69513df4626SMatt Arsenault case Check::CheckPlain: 69613df4626SMatt Arsenault return sizeof(":") - 1; 69713df4626SMatt Arsenault 69813df4626SMatt Arsenault case Check::CheckNext: 69913df4626SMatt Arsenault return sizeof("-NEXT:") - 1; 70013df4626SMatt Arsenault 70101ac1707SDuncan P. N. Exon Smith case Check::CheckSame: 70201ac1707SDuncan P. N. Exon Smith return sizeof("-SAME:") - 1; 70301ac1707SDuncan P. N. Exon Smith 70413df4626SMatt Arsenault case Check::CheckNot: 70513df4626SMatt Arsenault return sizeof("-NOT:") - 1; 70613df4626SMatt Arsenault 70713df4626SMatt Arsenault case Check::CheckDAG: 70813df4626SMatt Arsenault return sizeof("-DAG:") - 1; 70913df4626SMatt Arsenault 71013df4626SMatt Arsenault case Check::CheckLabel: 71113df4626SMatt Arsenault return sizeof("-LABEL:") - 1; 71213df4626SMatt Arsenault 71313df4626SMatt Arsenault case Check::CheckEOF: 71413df4626SMatt Arsenault llvm_unreachable("Should not be using EOF size"); 71513df4626SMatt Arsenault } 71613df4626SMatt Arsenault 71713df4626SMatt Arsenault llvm_unreachable("Bad check type"); 71813df4626SMatt Arsenault } 71913df4626SMatt Arsenault 72013df4626SMatt Arsenault static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) { 721*83e63d96SGeorge Rimar if (Buffer.size() <= Prefix.size()) 722*83e63d96SGeorge Rimar return Check::CheckNone; 723*83e63d96SGeorge Rimar 724c4d2d471SMatt Arsenault char NextChar = Buffer[Prefix.size()]; 72538820972SMatt Arsenault 72638820972SMatt Arsenault // Verify that the : is present after the prefix. 72713df4626SMatt Arsenault if (NextChar == ':') 72838820972SMatt Arsenault return Check::CheckPlain; 72938820972SMatt Arsenault 73013df4626SMatt Arsenault if (NextChar != '-') 73138820972SMatt Arsenault return Check::CheckNone; 73238820972SMatt Arsenault 733c4d2d471SMatt Arsenault StringRef Rest = Buffer.drop_front(Prefix.size() + 1); 73413df4626SMatt Arsenault if (Rest.startswith("NEXT:")) 73538820972SMatt Arsenault return Check::CheckNext; 73638820972SMatt Arsenault 73701ac1707SDuncan P. N. Exon Smith if (Rest.startswith("SAME:")) 73801ac1707SDuncan P. N. Exon Smith return Check::CheckSame; 73901ac1707SDuncan P. N. Exon Smith 74013df4626SMatt Arsenault if (Rest.startswith("NOT:")) 74138820972SMatt Arsenault return Check::CheckNot; 74238820972SMatt Arsenault 74313df4626SMatt Arsenault if (Rest.startswith("DAG:")) 74438820972SMatt Arsenault return Check::CheckDAG; 74538820972SMatt Arsenault 74613df4626SMatt Arsenault if (Rest.startswith("LABEL:")) 74738820972SMatt Arsenault return Check::CheckLabel; 74813df4626SMatt Arsenault 749a908e7bdSPaul Robinson // You can't combine -NOT with another suffix. 750a908e7bdSPaul Robinson if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") || 751a908e7bdSPaul Robinson Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") || 752a908e7bdSPaul Robinson Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:")) 753a908e7bdSPaul Robinson return Check::CheckBadNot; 754a908e7bdSPaul Robinson 75513df4626SMatt Arsenault return Check::CheckNone; 75638820972SMatt Arsenault } 75738820972SMatt Arsenault 75813df4626SMatt Arsenault // From the given position, find the next character after the word. 75913df4626SMatt Arsenault static size_t SkipWord(StringRef Str, size_t Loc) { 76013df4626SMatt Arsenault while (Loc < Str.size() && IsPartOfWord(Str[Loc])) 76113df4626SMatt Arsenault ++Loc; 76213df4626SMatt Arsenault return Loc; 76313df4626SMatt Arsenault } 76413df4626SMatt Arsenault 765726774cbSChandler Carruth /// Search the buffer for the first prefix in the prefix regular expression. 766726774cbSChandler Carruth /// 767726774cbSChandler Carruth /// This searches the buffer using the provided regular expression, however it 768726774cbSChandler Carruth /// enforces constraints beyond that: 769726774cbSChandler Carruth /// 1) The found prefix must not be a suffix of something that looks like 770726774cbSChandler Carruth /// a valid prefix. 771726774cbSChandler Carruth /// 2) The found prefix must be followed by a valid check type suffix using \c 772726774cbSChandler Carruth /// FindCheckType above. 773726774cbSChandler Carruth /// 774726774cbSChandler Carruth /// The first match of the regular expression to satisfy these two is returned, 775726774cbSChandler Carruth /// otherwise an empty StringRef is returned to indicate failure. 776726774cbSChandler Carruth /// 777726774cbSChandler Carruth /// If this routine returns a valid prefix, it will also shrink \p Buffer to 778726774cbSChandler Carruth /// start at the beginning of the returned prefix, increment \p LineNumber for 779726774cbSChandler Carruth /// each new line consumed from \p Buffer, and set \p CheckTy to the type of 780726774cbSChandler Carruth /// check found by examining the suffix. 781726774cbSChandler Carruth /// 782726774cbSChandler Carruth /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy 783726774cbSChandler Carruth /// is unspecified. 784726774cbSChandler Carruth static StringRef FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer, 78513df4626SMatt Arsenault unsigned &LineNumber, 786726774cbSChandler Carruth Check::CheckType &CheckTy) { 787726774cbSChandler Carruth SmallVector<StringRef, 2> Matches; 788726774cbSChandler Carruth 78913df4626SMatt Arsenault while (!Buffer.empty()) { 790726774cbSChandler Carruth // Find the first (longest) match using the RE. 791726774cbSChandler Carruth if (!PrefixRE.match(Buffer, &Matches)) 792726774cbSChandler Carruth // No match at all, bail. 793726774cbSChandler Carruth return StringRef(); 794726774cbSChandler Carruth 795726774cbSChandler Carruth StringRef Prefix = Matches[0]; 796726774cbSChandler Carruth Matches.clear(); 797726774cbSChandler Carruth 798726774cbSChandler Carruth assert(Prefix.data() >= Buffer.data() && 799726774cbSChandler Carruth Prefix.data() < Buffer.data() + Buffer.size() && 800726774cbSChandler Carruth "Prefix doesn't start inside of buffer!"); 801726774cbSChandler Carruth size_t Loc = Prefix.data() - Buffer.data(); 802726774cbSChandler Carruth StringRef Skipped = Buffer.substr(0, Loc); 803726774cbSChandler Carruth Buffer = Buffer.drop_front(Loc); 804726774cbSChandler Carruth LineNumber += Skipped.count('\n'); 805726774cbSChandler Carruth 806726774cbSChandler Carruth // Check that the matched prefix isn't a suffix of some other check-like 807726774cbSChandler Carruth // word. 808726774cbSChandler Carruth // FIXME: This is a very ad-hoc check. it would be better handled in some 809726774cbSChandler Carruth // other way. Among other things it seems hard to distinguish between 810726774cbSChandler Carruth // intentional and unintentional uses of this feature. 811726774cbSChandler Carruth if (Skipped.empty() || !IsPartOfWord(Skipped.back())) { 812726774cbSChandler Carruth // Now extract the type. 813726774cbSChandler Carruth CheckTy = FindCheckType(Buffer, Prefix); 814726774cbSChandler Carruth 815726774cbSChandler Carruth // If we've found a valid check type for this prefix, we're done. 816726774cbSChandler Carruth if (CheckTy != Check::CheckNone) 81713df4626SMatt Arsenault return Prefix; 81813df4626SMatt Arsenault } 81913df4626SMatt Arsenault 820726774cbSChandler Carruth // If we didn't successfully find a prefix, we need to skip this invalid 821726774cbSChandler Carruth // prefix and continue scanning. We directly skip the prefix that was 822726774cbSChandler Carruth // matched and any additional parts of that check-like word. 823726774cbSChandler Carruth Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size())); 82413df4626SMatt Arsenault } 82513df4626SMatt Arsenault 826726774cbSChandler Carruth // We ran out of buffer while skipping partial matches so give up. 82713df4626SMatt Arsenault return StringRef(); 82838820972SMatt Arsenault } 829ee3c74fbSChris Lattner 8304dabac20SChandler Carruth /// Read the check file, which specifies the sequence of expected strings. 8314dabac20SChandler Carruth /// 8324dabac20SChandler Carruth /// The strings are added to the CheckStrings vector. Returns true in case of 8334dabac20SChandler Carruth /// an error, false otherwise. 834726774cbSChandler Carruth static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, 83526cccfe1SChris Lattner std::vector<CheckString> &CheckStrings) { 83656ccdbbdSAlexander Kornienko std::vector<Pattern> ImplicitNegativeChecks; 83756ccdbbdSAlexander Kornienko for (const auto &PatternString : ImplicitCheckNot) { 83856ccdbbdSAlexander Kornienko // Create a buffer with fake command line content in order to display the 83956ccdbbdSAlexander Kornienko // command line option responsible for the specific implicit CHECK-NOT. 840ff43d69dSDavid Blaikie std::string Prefix = (Twine("-") + ImplicitCheckNot.ArgStr + "='").str(); 84156ccdbbdSAlexander Kornienko std::string Suffix = "'"; 8423560ff2cSRafael Espindola std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy( 8433560ff2cSRafael Espindola Prefix + PatternString + Suffix, "command line"); 8443560ff2cSRafael Espindola 84556ccdbbdSAlexander Kornienko StringRef PatternInBuffer = 84656ccdbbdSAlexander Kornienko CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); 8471961f14cSDavid Blaikie SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); 84856ccdbbdSAlexander Kornienko 84956ccdbbdSAlexander Kornienko ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); 85056ccdbbdSAlexander Kornienko ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, 85156ccdbbdSAlexander Kornienko "IMPLICIT-CHECK", SM, 0); 85256ccdbbdSAlexander Kornienko } 85356ccdbbdSAlexander Kornienko 85456ccdbbdSAlexander Kornienko std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks; 855236d2d5eSChris Lattner 85643d50d4aSEli Bendersky // LineNumber keeps track of the line on which CheckPrefix instances are 85743d50d4aSEli Bendersky // found. 85892987fb3SAlexander Kornienko unsigned LineNumber = 1; 85992987fb3SAlexander Kornienko 860ee3c74fbSChris Lattner while (1) { 86113df4626SMatt Arsenault Check::CheckType CheckTy; 86213df4626SMatt Arsenault 86313df4626SMatt Arsenault // See if a prefix occurs in the memory buffer. 864726774cbSChandler Carruth StringRef UsedPrefix = FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, 865726774cbSChandler Carruth CheckTy); 86613df4626SMatt Arsenault if (UsedPrefix.empty()) 867ee3c74fbSChris Lattner break; 868726774cbSChandler Carruth assert(UsedPrefix.data() == Buffer.data() && 869726774cbSChandler Carruth "Failed to move Buffer's start forward, or pointed prefix outside " 870726774cbSChandler Carruth "of the buffer!"); 87192987fb3SAlexander Kornienko 87213df4626SMatt Arsenault // Location to use for error messages. 873726774cbSChandler Carruth const char *UsedPrefixStart = UsedPrefix.data(); 87492987fb3SAlexander Kornienko 875726774cbSChandler Carruth // Skip the buffer to the end. 87613df4626SMatt Arsenault Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy)); 87710f10cedSChris Lattner 878a908e7bdSPaul Robinson // Complain about useful-looking but unsupported suffixes. 879a908e7bdSPaul Robinson if (CheckTy == Check::CheckBadNot) { 880e8f2fb20SChandler Carruth SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error, 881a908e7bdSPaul Robinson "unsupported -NOT combo on prefix '" + UsedPrefix + "'"); 882a908e7bdSPaul Robinson return true; 883a908e7bdSPaul Robinson } 884a908e7bdSPaul Robinson 88538820972SMatt Arsenault // Okay, we found the prefix, yay. Remember the rest of the line, but ignore 886a26bc914STom de Vries // leading whitespace. 8871714676aSTom de Vries if (!(NoCanonicalizeWhiteSpace && MatchFullLines)) 888236d2d5eSChris Lattner Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); 889ee3c74fbSChris Lattner 890ee3c74fbSChris Lattner // Scan ahead to the end of line. 891caa5fc0cSChris Lattner size_t EOL = Buffer.find_first_of("\n\r"); 892ee3c74fbSChris Lattner 893838fb09aSDan Gohman // Remember the location of the start of the pattern, for diagnostics. 894838fb09aSDan Gohman SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); 895838fb09aSDan Gohman 89674d50731SChris Lattner // Parse the pattern. 89738820972SMatt Arsenault Pattern P(CheckTy); 89813df4626SMatt Arsenault if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber)) 899ee3c74fbSChris Lattner return true; 900ee3c74fbSChris Lattner 901f8bd2e5bSStephen Lin // Verify that CHECK-LABEL lines do not define or use variables 90238820972SMatt Arsenault if ((CheckTy == Check::CheckLabel) && P.hasVariable()) { 903e8f2fb20SChandler Carruth SM.PrintMessage( 904e8f2fb20SChandler Carruth SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error, 90513df4626SMatt Arsenault "found '" + UsedPrefix + "-LABEL:'" 90613df4626SMatt Arsenault " with variable definition or use"); 907f8bd2e5bSStephen Lin return true; 908f8bd2e5bSStephen Lin } 909f8bd2e5bSStephen Lin 910236d2d5eSChris Lattner Buffer = Buffer.substr(EOL); 91174d50731SChris Lattner 912da108b4eSChris Lattner // Verify that CHECK-NEXT lines have at least one CHECK line before them. 91301ac1707SDuncan P. N. Exon Smith if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) && 91401ac1707SDuncan P. N. Exon Smith CheckStrings.empty()) { 91501ac1707SDuncan P. N. Exon Smith StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME"; 91613df4626SMatt Arsenault SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 91703b80a40SChris Lattner SourceMgr::DK_Error, 918e8f2fb20SChandler Carruth "found '" + UsedPrefix + "-" + Type + 919e8f2fb20SChandler Carruth "' without previous '" + UsedPrefix + ": line"); 920da108b4eSChris Lattner return true; 921da108b4eSChris Lattner } 922da108b4eSChris Lattner 92391a1b2c9SMichael Liao // Handle CHECK-DAG/-NOT. 92438820972SMatt Arsenault if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) { 92591a1b2c9SMichael Liao DagNotMatches.push_back(P); 92674d50731SChris Lattner continue; 92774d50731SChris Lattner } 92874d50731SChris Lattner 929ee3c74fbSChris Lattner // Okay, add the string we captured to the output vector and move on. 93085913ccaSJames Y Knight CheckStrings.emplace_back(P, UsedPrefix, PatternLoc); 93191a1b2c9SMichael Liao std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 93256ccdbbdSAlexander Kornienko DagNotMatches = ImplicitNegativeChecks; 933ee3c74fbSChris Lattner } 934ee3c74fbSChris Lattner 93513df4626SMatt Arsenault // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first 93613df4626SMatt Arsenault // prefix as a filler for the error message. 93791a1b2c9SMichael Liao if (!DagNotMatches.empty()) { 938f5e2fc47SBenjamin Kramer CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(), 93985913ccaSJames Y Knight SMLoc::getFromPointer(Buffer.data())); 94091a1b2c9SMichael Liao std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 941eba55822SJakob Stoklund Olesen } 942eba55822SJakob Stoklund Olesen 943ee3c74fbSChris Lattner if (CheckStrings.empty()) { 94413df4626SMatt Arsenault errs() << "error: no check strings found with prefix" 94513df4626SMatt Arsenault << (CheckPrefixes.size() > 1 ? "es " : " "); 9463e3ef2f2SChris Bieneman prefix_iterator I = CheckPrefixes.begin(); 9473e3ef2f2SChris Bieneman prefix_iterator E = CheckPrefixes.end(); 9483e3ef2f2SChris Bieneman if (I != E) { 9493e3ef2f2SChris Bieneman errs() << "\'" << *I << ":'"; 9503e3ef2f2SChris Bieneman ++I; 95113df4626SMatt Arsenault } 9523e3ef2f2SChris Bieneman for (; I != E; ++I) 9533e3ef2f2SChris Bieneman errs() << ", \'" << *I << ":'"; 95413df4626SMatt Arsenault 95513df4626SMatt Arsenault errs() << '\n'; 956ee3c74fbSChris Lattner return true; 957ee3c74fbSChris Lattner } 958ee3c74fbSChris Lattner 959ee3c74fbSChris Lattner return false; 960ee3c74fbSChris Lattner } 961ee3c74fbSChris Lattner 962e8f2fb20SChandler Carruth static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat, 963e8f2fb20SChandler Carruth StringRef Buffer, 964e0ef65abSDaniel Dunbar StringMap<StringRef> &VariableTable) { 965da108b4eSChris Lattner // Otherwise, we have an error, emit an error message. 96691a1b2c9SMichael Liao SM.PrintMessage(Loc, SourceMgr::DK_Error, 96703b80a40SChris Lattner "expected string not found in input"); 968da108b4eSChris Lattner 969da108b4eSChris Lattner // Print the "scanning from here" line. If the current position is at the 970da108b4eSChris Lattner // end of a line, advance to the start of the next line. 971caa5fc0cSChris Lattner Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r")); 972da108b4eSChris Lattner 97303b80a40SChris Lattner SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 97403b80a40SChris Lattner "scanning from here"); 975e0ef65abSDaniel Dunbar 976e0ef65abSDaniel Dunbar // Allow the pattern to print additional information if desired. 97791a1b2c9SMichael Liao Pat.PrintFailureInfo(SM, Buffer, VariableTable); 97891a1b2c9SMichael Liao } 97991a1b2c9SMichael Liao 98091a1b2c9SMichael Liao static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, 98191a1b2c9SMichael Liao StringRef Buffer, 98291a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) { 98391a1b2c9SMichael Liao PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable); 984da108b4eSChris Lattner } 985da108b4eSChris Lattner 9864dabac20SChandler Carruth /// Count the number of newlines in the specified range. 987592fe880SRichard Smith static unsigned CountNumNewlinesBetween(StringRef Range, 988592fe880SRichard Smith const char *&FirstNewLine) { 989da108b4eSChris Lattner unsigned NumNewLines = 0; 99037183584SChris Lattner while (1) { 991da108b4eSChris Lattner // Scan for newline. 99237183584SChris Lattner Range = Range.substr(Range.find_first_of("\n\r")); 993e8f2fb20SChandler Carruth if (Range.empty()) 994e8f2fb20SChandler Carruth return NumNewLines; 995da108b4eSChris Lattner 996da108b4eSChris Lattner ++NumNewLines; 997da108b4eSChris Lattner 998da108b4eSChris Lattner // Handle \n\r and \r\n as a single newline. 999e8f2fb20SChandler Carruth if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') && 100037183584SChris Lattner (Range[0] != Range[1])) 100137183584SChris Lattner Range = Range.substr(1); 100237183584SChris Lattner Range = Range.substr(1); 1003592fe880SRichard Smith 1004592fe880SRichard Smith if (NumNewLines == 1) 1005592fe880SRichard Smith FirstNewLine = Range.begin(); 1006da108b4eSChris Lattner } 1007da108b4eSChris Lattner } 1008da108b4eSChris Lattner 10094dabac20SChandler Carruth /// Match check string and its "not strings" and/or "dag strings". 1010dcc7d48dSMichael Liao size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, 1011e93a3a08SStephen Lin bool IsLabelScanMode, size_t &MatchLen, 1012dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const { 101391a1b2c9SMichael Liao size_t LastPos = 0; 101491a1b2c9SMichael Liao std::vector<const Pattern *> NotStrings; 101591a1b2c9SMichael Liao 1016e93a3a08SStephen Lin // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL 1017e93a3a08SStephen Lin // bounds; we have not processed variable definitions within the bounded block 1018e93a3a08SStephen Lin // yet so cannot handle any final CHECK-DAG yet; this is handled when going 1019e93a3a08SStephen Lin // over the block again (including the last CHECK-LABEL) in normal mode. 1020e93a3a08SStephen Lin if (!IsLabelScanMode) { 102191a1b2c9SMichael Liao // Match "dag strings" (with mixed "not strings" if any). 102291a1b2c9SMichael Liao LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable); 102391a1b2c9SMichael Liao if (LastPos == StringRef::npos) 102491a1b2c9SMichael Liao return StringRef::npos; 1025e93a3a08SStephen Lin } 102691a1b2c9SMichael Liao 102791a1b2c9SMichael Liao // Match itself from the last position after matching CHECK-DAG. 102891a1b2c9SMichael Liao StringRef MatchBuffer = Buffer.substr(LastPos); 102991a1b2c9SMichael Liao size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); 1030dcc7d48dSMichael Liao if (MatchPos == StringRef::npos) { 103191a1b2c9SMichael Liao PrintCheckFailed(SM, *this, MatchBuffer, VariableTable); 1032dcc7d48dSMichael Liao return StringRef::npos; 1033dcc7d48dSMichael Liao } 1034dcc7d48dSMichael Liao 1035e93a3a08SStephen Lin // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT 1036e93a3a08SStephen Lin // or CHECK-NOT 1037e93a3a08SStephen Lin if (!IsLabelScanMode) { 103891a1b2c9SMichael Liao StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 1039dcc7d48dSMichael Liao 1040dcc7d48dSMichael Liao // If this check is a "CHECK-NEXT", verify that the previous match was on 1041dcc7d48dSMichael Liao // the previous line (i.e. that there is one newline between them). 1042dcc7d48dSMichael Liao if (CheckNext(SM, SkippedRegion)) 1043dcc7d48dSMichael Liao return StringRef::npos; 1044dcc7d48dSMichael Liao 104501ac1707SDuncan P. N. Exon Smith // If this check is a "CHECK-SAME", verify that the previous match was on 104601ac1707SDuncan P. N. Exon Smith // the same line (i.e. that there is no newline between them). 104701ac1707SDuncan P. N. Exon Smith if (CheckSame(SM, SkippedRegion)) 104801ac1707SDuncan P. N. Exon Smith return StringRef::npos; 104901ac1707SDuncan P. N. Exon Smith 1050dcc7d48dSMichael Liao // If this match had "not strings", verify that they don't exist in the 1051dcc7d48dSMichael Liao // skipped region. 105291a1b2c9SMichael Liao if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) 1053dcc7d48dSMichael Liao return StringRef::npos; 1054f8bd2e5bSStephen Lin } 1055dcc7d48dSMichael Liao 10567dfb92b9SMehdi Amini return LastPos + MatchPos; 1057dcc7d48dSMichael Liao } 1058dcc7d48dSMichael Liao 10594dabac20SChandler Carruth /// Verify there is a single line in the given buffer. 1060dcc7d48dSMichael Liao bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { 106185913ccaSJames Y Knight if (Pat.getCheckTy() != Check::CheckNext) 1062dcc7d48dSMichael Liao return false; 1063dcc7d48dSMichael Liao 1064dcc7d48dSMichael Liao // Count the number of newlines between the previous match and this one. 1065dcc7d48dSMichael Liao assert(Buffer.data() != 1066e8f2fb20SChandler Carruth SM.getMemoryBuffer(SM.FindBufferContainingLoc( 1067e8f2fb20SChandler Carruth SMLoc::getFromPointer(Buffer.data()))) 1068e8f2fb20SChandler Carruth ->getBufferStart() && 1069dcc7d48dSMichael Liao "CHECK-NEXT can't be the first check in a file"); 1070dcc7d48dSMichael Liao 107166f09ad0SCraig Topper const char *FirstNewLine = nullptr; 1072592fe880SRichard Smith unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 1073dcc7d48dSMichael Liao 1074dcc7d48dSMichael Liao if (NumNewLines == 0) { 1075e8f2fb20SChandler Carruth SM.PrintMessage(Loc, SourceMgr::DK_Error, 1076e8f2fb20SChandler Carruth Prefix + "-NEXT: is on the same line as previous match"); 1077e8f2fb20SChandler Carruth SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 1078e8f2fb20SChandler Carruth "'next' match was here"); 1079dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1080dcc7d48dSMichael Liao "previous match ended here"); 1081dcc7d48dSMichael Liao return true; 1082dcc7d48dSMichael Liao } 1083dcc7d48dSMichael Liao 1084dcc7d48dSMichael Liao if (NumNewLines != 1) { 1085e8f2fb20SChandler Carruth SM.PrintMessage(Loc, SourceMgr::DK_Error, 1086e8f2fb20SChandler Carruth Prefix + 1087dcc7d48dSMichael Liao "-NEXT: is not on the line after the previous match"); 1088e8f2fb20SChandler Carruth SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 1089e8f2fb20SChandler Carruth "'next' match was here"); 1090dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1091dcc7d48dSMichael Liao "previous match ended here"); 1092592fe880SRichard Smith SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, 1093592fe880SRichard Smith "non-matching line after previous match is here"); 1094dcc7d48dSMichael Liao return true; 1095dcc7d48dSMichael Liao } 1096dcc7d48dSMichael Liao 1097dcc7d48dSMichael Liao return false; 1098dcc7d48dSMichael Liao } 1099dcc7d48dSMichael Liao 11004dabac20SChandler Carruth /// Verify there is no newline in the given buffer. 110101ac1707SDuncan P. N. Exon Smith bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { 110285913ccaSJames Y Knight if (Pat.getCheckTy() != Check::CheckSame) 110301ac1707SDuncan P. N. Exon Smith return false; 110401ac1707SDuncan P. N. Exon Smith 110501ac1707SDuncan P. N. Exon Smith // Count the number of newlines between the previous match and this one. 110601ac1707SDuncan P. N. Exon Smith assert(Buffer.data() != 110701ac1707SDuncan P. N. Exon Smith SM.getMemoryBuffer(SM.FindBufferContainingLoc( 110801ac1707SDuncan P. N. Exon Smith SMLoc::getFromPointer(Buffer.data()))) 110901ac1707SDuncan P. N. Exon Smith ->getBufferStart() && 111001ac1707SDuncan P. N. Exon Smith "CHECK-SAME can't be the first check in a file"); 111101ac1707SDuncan P. N. Exon Smith 111201ac1707SDuncan P. N. Exon Smith const char *FirstNewLine = nullptr; 111301ac1707SDuncan P. N. Exon Smith unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 111401ac1707SDuncan P. N. Exon Smith 111501ac1707SDuncan P. N. Exon Smith if (NumNewLines != 0) { 111601ac1707SDuncan P. N. Exon Smith SM.PrintMessage(Loc, SourceMgr::DK_Error, 111701ac1707SDuncan P. N. Exon Smith Prefix + 111801ac1707SDuncan P. N. Exon Smith "-SAME: is not on the same line as the previous match"); 111901ac1707SDuncan P. N. Exon Smith SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 112001ac1707SDuncan P. N. Exon Smith "'next' match was here"); 112101ac1707SDuncan P. N. Exon Smith SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 112201ac1707SDuncan P. N. Exon Smith "previous match ended here"); 112301ac1707SDuncan P. N. Exon Smith return true; 112401ac1707SDuncan P. N. Exon Smith } 112501ac1707SDuncan P. N. Exon Smith 112601ac1707SDuncan P. N. Exon Smith return false; 112701ac1707SDuncan P. N. Exon Smith } 112801ac1707SDuncan P. N. Exon Smith 11294dabac20SChandler Carruth /// Verify there's no "not strings" in the given buffer. 1130dcc7d48dSMichael Liao bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer, 113191a1b2c9SMichael Liao const std::vector<const Pattern *> &NotStrings, 1132dcc7d48dSMichael Liao StringMap<StringRef> &VariableTable) const { 11338f870499SBenjamin Kramer for (const Pattern *Pat : NotStrings) { 113438820972SMatt Arsenault assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!"); 113591a1b2c9SMichael Liao 1136dcc7d48dSMichael Liao size_t MatchLen = 0; 113791a1b2c9SMichael Liao size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable); 1138dcc7d48dSMichael Liao 1139e8f2fb20SChandler Carruth if (Pos == StringRef::npos) 1140e8f2fb20SChandler Carruth continue; 1141dcc7d48dSMichael Liao 1142dcc7d48dSMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos), 1143e8f2fb20SChandler Carruth SourceMgr::DK_Error, Prefix + "-NOT: string occurred!"); 114491a1b2c9SMichael Liao SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note, 114513df4626SMatt Arsenault Prefix + "-NOT: pattern specified here"); 1146dcc7d48dSMichael Liao return true; 1147dcc7d48dSMichael Liao } 1148dcc7d48dSMichael Liao 1149dcc7d48dSMichael Liao return false; 1150dcc7d48dSMichael Liao } 1151dcc7d48dSMichael Liao 11524dabac20SChandler Carruth /// Match "dag strings" and their mixed "not strings". 115391a1b2c9SMichael Liao size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, 115491a1b2c9SMichael Liao std::vector<const Pattern *> &NotStrings, 115591a1b2c9SMichael Liao StringMap<StringRef> &VariableTable) const { 115691a1b2c9SMichael Liao if (DagNotStrings.empty()) 115791a1b2c9SMichael Liao return 0; 115891a1b2c9SMichael Liao 115991a1b2c9SMichael Liao size_t LastPos = 0; 116091a1b2c9SMichael Liao size_t StartPos = LastPos; 116191a1b2c9SMichael Liao 11628f870499SBenjamin Kramer for (const Pattern &Pat : DagNotStrings) { 116338820972SMatt Arsenault assert((Pat.getCheckTy() == Check::CheckDAG || 116438820972SMatt Arsenault Pat.getCheckTy() == Check::CheckNot) && 116591a1b2c9SMichael Liao "Invalid CHECK-DAG or CHECK-NOT!"); 116691a1b2c9SMichael Liao 116738820972SMatt Arsenault if (Pat.getCheckTy() == Check::CheckNot) { 116891a1b2c9SMichael Liao NotStrings.push_back(&Pat); 116991a1b2c9SMichael Liao continue; 117091a1b2c9SMichael Liao } 117191a1b2c9SMichael Liao 117238820972SMatt Arsenault assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!"); 117391a1b2c9SMichael Liao 117491a1b2c9SMichael Liao size_t MatchLen = 0, MatchPos; 117591a1b2c9SMichael Liao 117691a1b2c9SMichael Liao // CHECK-DAG always matches from the start. 117791a1b2c9SMichael Liao StringRef MatchBuffer = Buffer.substr(StartPos); 117891a1b2c9SMichael Liao MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); 117991a1b2c9SMichael Liao // With a group of CHECK-DAGs, a single mismatching means the match on 118091a1b2c9SMichael Liao // that group of CHECK-DAGs fails immediately. 118191a1b2c9SMichael Liao if (MatchPos == StringRef::npos) { 118291a1b2c9SMichael Liao PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable); 118391a1b2c9SMichael Liao return StringRef::npos; 118491a1b2c9SMichael Liao } 118591a1b2c9SMichael Liao // Re-calc it as the offset relative to the start of the original string. 118691a1b2c9SMichael Liao MatchPos += StartPos; 118791a1b2c9SMichael Liao 118891a1b2c9SMichael Liao if (!NotStrings.empty()) { 118991a1b2c9SMichael Liao if (MatchPos < LastPos) { 119091a1b2c9SMichael Liao // Reordered? 119191a1b2c9SMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos), 119291a1b2c9SMichael Liao SourceMgr::DK_Error, 119313df4626SMatt Arsenault Prefix + "-DAG: found a match of CHECK-DAG" 119491a1b2c9SMichael Liao " reordering across a CHECK-NOT"); 119591a1b2c9SMichael Liao SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos), 119691a1b2c9SMichael Liao SourceMgr::DK_Note, 119713df4626SMatt Arsenault Prefix + "-DAG: the farthest match of CHECK-DAG" 119891a1b2c9SMichael Liao " is found here"); 119991a1b2c9SMichael Liao SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note, 120013df4626SMatt Arsenault Prefix + "-NOT: the crossed pattern specified" 120191a1b2c9SMichael Liao " here"); 120291a1b2c9SMichael Liao SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note, 120313df4626SMatt Arsenault Prefix + "-DAG: the reordered pattern specified" 120491a1b2c9SMichael Liao " here"); 120591a1b2c9SMichael Liao return StringRef::npos; 120691a1b2c9SMichael Liao } 120791a1b2c9SMichael Liao // All subsequent CHECK-DAGs should be matched from the farthest 120891a1b2c9SMichael Liao // position of all precedent CHECK-DAGs (including this one.) 120991a1b2c9SMichael Liao StartPos = LastPos; 121091a1b2c9SMichael Liao // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to 121191a1b2c9SMichael Liao // CHECK-DAG, verify that there's no 'not' strings occurred in that 121291a1b2c9SMichael Liao // region. 1213cf60ab31SBenjamin Kramer StringRef SkippedRegion = Buffer.slice(LastPos, MatchPos); 1214cf708c32STim Northover if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) 121591a1b2c9SMichael Liao return StringRef::npos; 121691a1b2c9SMichael Liao // Clear "not strings". 121791a1b2c9SMichael Liao NotStrings.clear(); 121891a1b2c9SMichael Liao } 121991a1b2c9SMichael Liao 122091a1b2c9SMichael Liao // Update the last position with CHECK-DAG matches. 122191a1b2c9SMichael Liao LastPos = std::max(MatchPos + MatchLen, LastPos); 122291a1b2c9SMichael Liao } 122391a1b2c9SMichael Liao 122491a1b2c9SMichael Liao return LastPos; 122591a1b2c9SMichael Liao } 122691a1b2c9SMichael Liao 122713df4626SMatt Arsenault // A check prefix must contain only alphanumeric, hyphens and underscores. 122813df4626SMatt Arsenault static bool ValidateCheckPrefix(StringRef CheckPrefix) { 122913df4626SMatt Arsenault Regex Validator("^[a-zA-Z0-9_-]*$"); 123013df4626SMatt Arsenault return Validator.match(CheckPrefix); 123113df4626SMatt Arsenault } 123213df4626SMatt Arsenault 123313df4626SMatt Arsenault static bool ValidateCheckPrefixes() { 123413df4626SMatt Arsenault StringSet<> PrefixSet; 123513df4626SMatt Arsenault 12368f870499SBenjamin Kramer for (StringRef Prefix : CheckPrefixes) { 123724412b14SEli Bendersky // Reject empty prefixes. 123824412b14SEli Bendersky if (Prefix == "") 123924412b14SEli Bendersky return false; 124024412b14SEli Bendersky 12410356975cSDavid Blaikie if (!PrefixSet.insert(Prefix).second) 124213df4626SMatt Arsenault return false; 124313df4626SMatt Arsenault 124413df4626SMatt Arsenault if (!ValidateCheckPrefix(Prefix)) 124513df4626SMatt Arsenault return false; 124613df4626SMatt Arsenault } 124713df4626SMatt Arsenault 124813df4626SMatt Arsenault return true; 124913df4626SMatt Arsenault } 125013df4626SMatt Arsenault 1251726774cbSChandler Carruth // Combines the check prefixes into a single regex so that we can efficiently 1252726774cbSChandler Carruth // scan for any of the set. 1253726774cbSChandler Carruth // 1254726774cbSChandler Carruth // The semantics are that the longest-match wins which matches our regex 1255726774cbSChandler Carruth // library. 1256726774cbSChandler Carruth static Regex buildCheckPrefixRegex() { 125713df4626SMatt Arsenault // I don't think there's a way to specify an initial value for cl::list, 125813df4626SMatt Arsenault // so if nothing was specified, add the default 125913df4626SMatt Arsenault if (CheckPrefixes.empty()) 126013df4626SMatt Arsenault CheckPrefixes.push_back("CHECK"); 1261726774cbSChandler Carruth 1262726774cbSChandler Carruth // We already validated the contents of CheckPrefixes so just concatenate 1263726774cbSChandler Carruth // them as alternatives. 1264726774cbSChandler Carruth SmallString<32> PrefixRegexStr; 1265726774cbSChandler Carruth for (StringRef Prefix : CheckPrefixes) { 1266726774cbSChandler Carruth if (Prefix != CheckPrefixes.front()) 1267726774cbSChandler Carruth PrefixRegexStr.push_back('|'); 1268726774cbSChandler Carruth 1269726774cbSChandler Carruth PrefixRegexStr.append(Prefix); 1270726774cbSChandler Carruth } 1271726774cbSChandler Carruth 1272726774cbSChandler Carruth return Regex(PrefixRegexStr); 1273c2735158SRui Ueyama } 1274c2735158SRui Ueyama 12752bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) { 12762bd4f8b6SXinliang David Li errs() << "FileCheck command line: "; 12772bd4f8b6SXinliang David Li for (int I = 0; I < argc; I++) 12782bd4f8b6SXinliang David Li errs() << " " << argv[I]; 12792bd4f8b6SXinliang David Li errs() << "\n"; 12802bd4f8b6SXinliang David Li } 12812bd4f8b6SXinliang David Li 1282f55e72a5SArtem Belevich // Remove local variables from \p VariableTable. Global variables 1283f55e72a5SArtem Belevich // (start with '$') are preserved. 1284f55e72a5SArtem Belevich static void ClearLocalVars(StringMap<StringRef> &VariableTable) { 1285f55e72a5SArtem Belevich SmallVector<StringRef, 16> LocalVars; 1286f55e72a5SArtem Belevich for (const auto &Var : VariableTable) 1287f55e72a5SArtem Belevich if (Var.first()[0] != '$') 1288f55e72a5SArtem Belevich LocalVars.push_back(Var.first()); 1289f55e72a5SArtem Belevich 1290f55e72a5SArtem Belevich for (const auto &Var : LocalVars) 1291f55e72a5SArtem Belevich VariableTable.erase(Var); 1292f55e72a5SArtem Belevich } 1293f55e72a5SArtem Belevich 129420247900SChandler Carruth /// Check the input to FileCheck provided in the \p Buffer against the \p 129520247900SChandler Carruth /// CheckStrings read from the check file. 129620247900SChandler Carruth /// 129720247900SChandler Carruth /// Returns false if the input fails to satisfy the checks. 129820247900SChandler Carruth bool CheckInput(SourceMgr &SM, StringRef Buffer, 129920247900SChandler Carruth ArrayRef<CheckString> CheckStrings) { 130020247900SChandler Carruth bool ChecksFailed = false; 130120247900SChandler Carruth 130220247900SChandler Carruth /// VariableTable - This holds all the current filecheck variables. 130320247900SChandler Carruth StringMap<StringRef> VariableTable; 130420247900SChandler Carruth 130546e1fd61SAlexander Richardson for (const auto& Def : GlobalDefines) 130646e1fd61SAlexander Richardson VariableTable.insert(StringRef(Def).split('=')); 130746e1fd61SAlexander Richardson 130820247900SChandler Carruth unsigned i = 0, j = 0, e = CheckStrings.size(); 130920247900SChandler Carruth while (true) { 131020247900SChandler Carruth StringRef CheckRegion; 131120247900SChandler Carruth if (j == e) { 131220247900SChandler Carruth CheckRegion = Buffer; 131320247900SChandler Carruth } else { 131420247900SChandler Carruth const CheckString &CheckLabelStr = CheckStrings[j]; 131520247900SChandler Carruth if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { 131620247900SChandler Carruth ++j; 131720247900SChandler Carruth continue; 131820247900SChandler Carruth } 131920247900SChandler Carruth 132020247900SChandler Carruth // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG 132120247900SChandler Carruth size_t MatchLabelLen = 0; 1322e8f2fb20SChandler Carruth size_t MatchLabelPos = 1323e8f2fb20SChandler Carruth CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, VariableTable); 132420247900SChandler Carruth if (MatchLabelPos == StringRef::npos) 132520247900SChandler Carruth // Immediately bail of CHECK-LABEL fails, nothing else we can do. 132620247900SChandler Carruth return false; 132720247900SChandler Carruth 132820247900SChandler Carruth CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen); 132920247900SChandler Carruth Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen); 133020247900SChandler Carruth ++j; 133120247900SChandler Carruth } 133220247900SChandler Carruth 1333f55e72a5SArtem Belevich if (EnableVarScope) 1334f55e72a5SArtem Belevich ClearLocalVars(VariableTable); 1335f55e72a5SArtem Belevich 133620247900SChandler Carruth for (; i != j; ++i) { 133720247900SChandler Carruth const CheckString &CheckStr = CheckStrings[i]; 133820247900SChandler Carruth 133920247900SChandler Carruth // Check each string within the scanned region, including a second check 134020247900SChandler Carruth // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) 134120247900SChandler Carruth size_t MatchLen = 0; 1342e8f2fb20SChandler Carruth size_t MatchPos = 1343e8f2fb20SChandler Carruth CheckStr.Check(SM, CheckRegion, false, MatchLen, VariableTable); 134420247900SChandler Carruth 134520247900SChandler Carruth if (MatchPos == StringRef::npos) { 134620247900SChandler Carruth ChecksFailed = true; 134720247900SChandler Carruth i = j; 134820247900SChandler Carruth break; 134920247900SChandler Carruth } 135020247900SChandler Carruth 135120247900SChandler Carruth CheckRegion = CheckRegion.substr(MatchPos + MatchLen); 135220247900SChandler Carruth } 135320247900SChandler Carruth 135420247900SChandler Carruth if (j == e) 135520247900SChandler Carruth break; 135620247900SChandler Carruth } 135720247900SChandler Carruth 135820247900SChandler Carruth // Success if no checks failed. 135920247900SChandler Carruth return !ChecksFailed; 136020247900SChandler Carruth } 136120247900SChandler Carruth 1362ee3c74fbSChris Lattner int main(int argc, char **argv) { 13632ad6d48bSRichard Smith sys::PrintStackTraceOnErrorSignal(argv[0]); 1364ee3c74fbSChris Lattner PrettyStackTraceProgram X(argc, argv); 1365ee3c74fbSChris Lattner cl::ParseCommandLineOptions(argc, argv); 1366ee3c74fbSChris Lattner 136713df4626SMatt Arsenault if (!ValidateCheckPrefixes()) { 136813df4626SMatt Arsenault errs() << "Supplied check-prefix is invalid! Prefixes must be unique and " 136913df4626SMatt Arsenault "start with a letter and contain only alphanumeric characters, " 137013df4626SMatt Arsenault "hyphens and underscores\n"; 1371c2735158SRui Ueyama return 2; 1372c2735158SRui Ueyama } 1373c2735158SRui Ueyama 1374726774cbSChandler Carruth Regex PrefixRE = buildCheckPrefixRegex(); 1375726774cbSChandler Carruth std::string REError; 1376726774cbSChandler Carruth if (!PrefixRE.isValid(REError)) { 1377726774cbSChandler Carruth errs() << "Unable to combine check-prefix strings into a prefix regular " 1378726774cbSChandler Carruth "expression! This is likely a bug in FileCheck's verification of " 1379726774cbSChandler Carruth "the check-prefix strings. Regular expression parsing failed " 1380726774cbSChandler Carruth "with the following error: " 1381726774cbSChandler Carruth << REError << "\n"; 1382726774cbSChandler Carruth return 2; 1383726774cbSChandler Carruth } 138413df4626SMatt Arsenault 1385ee3c74fbSChris Lattner SourceMgr SM; 1386ee3c74fbSChris Lattner 1387ee3c74fbSChris Lattner // Read the expected strings from the check file. 138820247900SChandler Carruth ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr = 138920247900SChandler Carruth MemoryBuffer::getFileOrSTDIN(CheckFilename); 139020247900SChandler Carruth if (std::error_code EC = CheckFileOrErr.getError()) { 139120247900SChandler Carruth errs() << "Could not open check file '" << CheckFilename 139220247900SChandler Carruth << "': " << EC.message() << '\n'; 139320247900SChandler Carruth return 2; 139420247900SChandler Carruth } 139520247900SChandler Carruth MemoryBuffer &CheckFile = *CheckFileOrErr.get(); 139620247900SChandler Carruth 139720247900SChandler Carruth SmallString<4096> CheckFileBuffer; 1398b03c166aSChandler Carruth StringRef CheckFileText = CanonicalizeFile(CheckFile, CheckFileBuffer); 139920247900SChandler Carruth 140020247900SChandler Carruth SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 140120247900SChandler Carruth CheckFileText, CheckFile.getBufferIdentifier()), 140220247900SChandler Carruth SMLoc()); 140320247900SChandler Carruth 140426cccfe1SChris Lattner std::vector<CheckString> CheckStrings; 1405726774cbSChandler Carruth if (ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings)) 1406ee3c74fbSChris Lattner return 2; 1407ee3c74fbSChris Lattner 1408ee3c74fbSChris Lattner // Open the file to check and add it to SourceMgr. 140920247900SChandler Carruth ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr = 1410adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(InputFilename); 141120247900SChandler Carruth if (std::error_code EC = InputFileOrErr.getError()) { 1412adf21f2aSRafael Espindola errs() << "Could not open input file '" << InputFilename 1413adf21f2aSRafael Espindola << "': " << EC.message() << '\n'; 14148e1c6477SEli Bendersky return 2; 1415ee3c74fbSChris Lattner } 141620247900SChandler Carruth MemoryBuffer &InputFile = *InputFileOrErr.get(); 14172c3e5cdfSChris Lattner 141820247900SChandler Carruth if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) { 1419b692bed7SChris Lattner errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 14202bd4f8b6SXinliang David Li DumpCommandLine(argc, argv); 14218e1c6477SEli Bendersky return 2; 1422b692bed7SChris Lattner } 1423b692bed7SChris Lattner 142420247900SChandler Carruth SmallString<4096> InputFileBuffer; 1425b03c166aSChandler Carruth StringRef InputFileText = CanonicalizeFile(InputFile, InputFileBuffer); 14262c3e5cdfSChris Lattner 1427e8f2fb20SChandler Carruth SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 1428e8f2fb20SChandler Carruth InputFileText, InputFile.getBufferIdentifier()), 1429e8f2fb20SChandler Carruth SMLoc()); 1430ee3c74fbSChris Lattner 143120247900SChandler Carruth return CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1; 1432ee3c74fbSChris Lattner } 1433