1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===- FileCheck.cpp - Check that File's Contents match what is expected --===// 2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// 3894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// The LLVM Compiler Infrastructure 4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// 5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file is distributed under the University of Illinois Open Source 6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// License. See LICENSE.TXT for details. 7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// 8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===// 9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// 10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// FileCheck does a line-by line check of a file that validates whether it 11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// contains the expected content. This is useful for regression tests etc. 12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// 13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This program exits with an error status of 2 on error, exit status of 0 if 14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// the file matched the expected contents, and exit status of 1 if it did not 15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// contain the expected contents. 16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// 17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===// 18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/OwningPtr.h" 20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/CommandLine.h" 21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/MemoryBuffer.h" 22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/PrettyStackTrace.h" 23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/Regex.h" 24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/SourceMgr.h" 25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/raw_ostream.h" 2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/Signals.h" 2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/system_error.h" 28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/ADT/SmallString.h" 29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/ADT/StringMap.h" 30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <algorithm> 31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanusing namespace llvm; 32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic cl::opt<std::string> 34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanCheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required); 35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic cl::opt<std::string> 37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanInputFilename("input-file", cl::desc("File to check (defaults to stdin)"), 38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman cl::init("-"), cl::value_desc("filename")); 39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic cl::opt<std::string> 41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanCheckPrefix("check-prefix", cl::init("CHECK"), 42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman cl::desc("Prefix to use from check file (defaults to 'CHECK')")); 43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic cl::opt<bool> 45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanNoCanonicalizeWhiteSpace("strict-whitespace", 46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman cl::desc("Do not treat all horizontal whitespace as equivalent")); 47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===// 49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Pattern Handling Code. 50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===// 51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanclass Pattern { 53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SMLoc PatternLoc; 5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman /// MatchEOF - When set, this pattern only matches the end of file. This is 5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman /// used for trailing CHECK-NOTs. 5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool MatchEOF; 5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// FixedStr - If non-empty, this pattern is a fixed string match with the 60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// specified fixed string. 61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef FixedStr; 6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// RegEx - If non-empty, this is a regex pattern. 64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::string RegExStr; 6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// VariableUses - Entries in this vector map to uses of a variable in the 67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// pattern, e.g. "foo[[bar]]baz". In this case, the RegExStr will contain 68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// "foobaz" and we'll get an entry in this vector that tells us to insert the 69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// value of bar at offset 3. 70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::vector<std::pair<StringRef, unsigned> > VariableUses; 7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// VariableDefs - Entries in this vector map to definitions of a variable in 73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// the pattern, e.g. "foo[[bar:.*]]baz". In this case, the RegExStr will 74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// contain "foo(.*)baz" and VariableDefs will contain the pair "bar",1. The 75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// index indicates what parenthesized value captures the variable value. 76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::vector<std::pair<StringRef, unsigned> > VariableDefs; 7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanpublic: 7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { } 8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman bool ParsePattern(StringRef PatternStr, SourceMgr &SM); 8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// Match - Match the pattern string against the input buffer Buffer. This 85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// returns the position that is matched or npos if there is no match. If 86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// there is a match, the size of the matched string is returned in MatchLen. 87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// 88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// The VariableTable StringMap provides the current values of filecheck 89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// variables and is updated if this match defines new values. 90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t Match(StringRef Buffer, size_t &MatchLen, 91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringMap<StringRef> &VariableTable) const; 92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// PrintFailureInfo - Print additional information about a failure to match 94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// involving this pattern. 95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const StringMap<StringRef> &VariableTable) const; 97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanprivate: 99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr); 100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman bool AddRegExToRegEx(StringRef RegExStr, unsigned &CurParen, SourceMgr &SM); 101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of 103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// matching this pattern at the start of \arg Buffer; a distance of zero 104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// should correspond to a perfect match. 105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman unsigned ComputeMatchDistance(StringRef Buffer, 106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const StringMap<StringRef> &VariableTable) const; 107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}; 108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanbool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { 111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternLoc = SMLoc::getFromPointer(PatternStr.data()); 11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Ignore trailing whitespace. 114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman while (!PatternStr.empty() && 115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman (PatternStr.back() == ' ' || PatternStr.back() == '\t')) 116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternStr = PatternStr.substr(0, PatternStr.size()-1); 11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Check that there is something on the line. 119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (PatternStr.empty()) { 120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(PatternLoc, "found empty check string with prefix '" + 121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckPrefix+":'", "error"); 122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Check to see if this is a fixed string, or if it has regex pieces. 126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (PatternStr.size() < 2 || 127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman (PatternStr.find("{{") == StringRef::npos && 128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternStr.find("[[") == StringRef::npos)) { 129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman FixedStr = PatternStr; 130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return false; 131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Paren value #0 is for the fully matched string. Any new parenthesized 13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // values add from there. 135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman unsigned CurParen = 1; 13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Otherwise, there is at least one regex piece. Build up the regex pattern 138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // by escaping scary characters in fixed strings, building up one big regex. 139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman while (!PatternStr.empty()) { 140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // RegEx matches. 14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (PatternStr.startswith("{{")) { 14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Otherwise, this is the start of a regex match. Scan for the }}. 144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t End = PatternStr.find("}}"); 145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (End == StringRef::npos) { 146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman "found start of regex string with no end '}}'","error"); 148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Enclose {{}} patterns in parens just like [[]] even though we're not 15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // capturing the result for any purpose. This is required in case the 15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // expression contains an alternation like: CHECK: abc{{x|z}}def. We 15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // want this to turn into: "abc(x|z)def" not "abcx|zdef". 15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman RegExStr += '('; 15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ++CurParen; 15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) 159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman RegExStr += ')'; 16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternStr = PatternStr.substr(End+2); 163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* 167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // (or some other regex) and assigns it to the FileCheck variable 'foo'. The 168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // second form is [[foo]] which is a reference to foo. The variable name 169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject 170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // it. This is to catch some common errors. 17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (PatternStr.startswith("[[")) { 172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Verify that it is terminated properly. 173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t End = PatternStr.find("]]"); 174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (End == StringRef::npos) { 175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "invalid named regex reference, no ]] found", "error"); 177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 17919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef MatchStr = PatternStr.substr(2, End-2); 181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternStr = PatternStr.substr(End+2); 18219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Get the regex name (e.g. "foo"). 184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t NameEnd = MatchStr.find(':'); 185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef Name = MatchStr.substr(0, NameEnd); 18619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Name.empty()) { 188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "invalid name in named regex: empty name", "error"); 190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Verify that the name is well formed. 194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned i = 0, e = Name.size(); i != e; ++i) 19519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Name[i] != '_' && !isalnum(Name[i])) { 196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), 197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "invalid name in named regex", "error"); 198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 20019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Name can't start with a digit. 202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (isdigit(Name[0])) { 203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "invalid name in named regex", "error"); 205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 20719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Handle [[foo]]. 209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (NameEnd == StringRef::npos) { 210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman VariableUses.push_back(std::make_pair(Name, RegExStr.size())); 211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 21319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Handle [[foo:.*]]. 215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman VariableDefs.push_back(std::make_pair(Name, CurParen)); 216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman RegExStr += '('; 217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman ++CurParen; 21819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) 220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman RegExStr += ')'; 223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 22419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Handle fixed string matches. 226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Find the end, which is the start of the next regex. 227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t FixedMatchEnd = PatternStr.find("{{"); 228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); 229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); 230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternStr = PatternStr.substr(FixedMatchEnd); 231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return false; 235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) { 238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Add the characters from FixedStr to the regex, escaping as needed. This 239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // avoids "leaning toothpicks" in common patterns. 240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned i = 0, e = FixedStr.size(); i != e; ++i) { 241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman switch (FixedStr[i]) { 242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // These are the special characters matched in "p_ere_exp". 243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '(': 244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case ')': 245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '^': 246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '$': 247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '|': 248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '*': 249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '+': 250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '?': 251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '.': 252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '[': 253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '\\': 254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman case '{': 255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman TheStr += '\\'; 256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // FALL THROUGH. 257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman default: 258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman TheStr += FixedStr[i]; 259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman break; 260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanbool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen, 265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SourceMgr &SM) { 266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Regex R(RegexStr); 267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::string Error; 268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!R.isValid(Error)) { 269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(RegexStr.data()), 270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "invalid regex: " + Error, "error"); 271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 27319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman RegExStr += RegexStr.str(); 275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CurParen += R.getNumMatches(); 276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return false; 277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// Match - Match the pattern string against the input buffer Buffer. This 280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// returns the position that is matched or npos if there is no match. If 281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// there is a match, the size of the matched string is returned in MatchLen. 282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumansize_t Pattern::Match(StringRef Buffer, size_t &MatchLen, 283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringMap<StringRef> &VariableTable) const { 28419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // If this is the EOF pattern, match it immediately. 28519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (MatchEOF) { 28619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MatchLen = 0; 28719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Buffer.size(); 28819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 28919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If this is a fixed string pattern, just match it now. 291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!FixedStr.empty()) { 292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman MatchLen = FixedStr.size(); 293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Buffer.find(FixedStr); 294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Regex match. 29719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If there are variable uses, we need to create a temporary string with the 299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // actual value. 300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef RegExToMatch = RegExStr; 301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::string TmpStr; 302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!VariableUses.empty()) { 303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman TmpStr = RegExStr; 30419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman unsigned InsertOffset = 0; 306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { 307894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringMap<StringRef>::iterator it = 308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman VariableTable.find(VariableUses[i].first); 309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If the variable is undefined, return an error. 310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (it == VariableTable.end()) 311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return StringRef::npos; 312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Look up the value and escape it so that we can plop it into the regex. 314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::string Value; 315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman AddFixedStringToRegEx(it->second, Value); 31619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Plop it into the regex at the adjusted offset. 318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset, 319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Value.begin(), Value.end()); 320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman InsertOffset += Value.size(); 321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 32219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Match the newly constructed regex. 324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman RegExToMatch = TmpStr; 325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 32619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 32719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SmallVector<StringRef, 4> MatchInfo; 329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo)) 330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return StringRef::npos; 33119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Successful regex match. 333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman assert(!MatchInfo.empty() && "Didn't get any match"); 334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef FullMatch = MatchInfo[0]; 33519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If this defines any variables, remember their values. 337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) { 338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman assert(VariableDefs[i].second < MatchInfo.size() && 339894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "Internal paren error"); 340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second]; 341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 34219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman MatchLen = FullMatch.size(); 344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return FullMatch.data()-Buffer.data(); 345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanunsigned Pattern::ComputeMatchDistance(StringRef Buffer, 348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const StringMap<StringRef> &VariableTable) const { 349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Just compute the number of matching characters. For regular expressions, we 350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // just compare against the regex itself and hope for the best. 351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // 352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // FIXME: One easy improvement here is have the regex lib generate a single 353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // example regular expression which matches, and use that as the example 354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // string. 355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef ExampleString(FixedStr); 356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (ExampleString.empty()) 357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman ExampleString = RegExStr; 358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Only compare up to the first line in the buffer, or the string size. 360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef BufferPrefix = Buffer.substr(0, ExampleString.size()); 361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman BufferPrefix = BufferPrefix.split('\n').first; 362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return BufferPrefix.edit_distance(ExampleString); 363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, 366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const StringMap<StringRef> &VariableTable) const{ 367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If this was a regular expression using variables, print the current 368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // variable values. 369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!VariableUses.empty()) { 370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { 371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef Var = VariableUses[i].first; 372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringMap<StringRef>::const_iterator it = VariableTable.find(Var); 373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SmallString<256> Msg; 374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman raw_svector_ostream OS(Msg); 375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Check for undefined variable references. 377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (it == VariableTable.end()) { 378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman OS << "uses undefined variable \""; 379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman OS.write_escaped(Var) << "\"";; 380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } else { 381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman OS << "with variable \""; 382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman OS.write_escaped(Var) << "\" equal to \""; 383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman OS.write_escaped(it->second) << "\""; 384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), OS.str(), "note", 387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /*ShowLine=*/false); 388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Attempt to find the closest/best fuzzy match. Usually an error happens 392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // because some string in the output didn't exactly match. In these cases, we 393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // would like to show the user a best guess at what "should have" matched, to 394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // save them having to actually check the input manually. 395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t NumLinesForward = 0; 396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t Best = StringRef::npos; 397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman double BestQuality = 0; 398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Use an arbitrary 4k limit on how far we will search. 400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { 401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Buffer[i] == '\n') 402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman ++NumLinesForward; 403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Patterns have leading whitespace stripped, so skip whitespace when 405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // looking for something which looks like a pattern. 406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Buffer[i] == ' ' || Buffer[i] == '\t') 407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Compute the "quality" of this match as an arbitrary combination of the 410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // match distance and the number of lines skipped to get to this match. 411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); 412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman double Quality = Distance + (NumLinesForward / 100.); 413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Quality < BestQuality || Best == StringRef::npos) { 415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Best = i; 416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman BestQuality = Quality; 417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 420894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Print the "possible intended match here" line if we found something 421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // reasonable and not equal to what we showed in the "scanning from here" 422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // line. 423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Best && Best != StringRef::npos && BestQuality < 50) { 424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), 425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "possible intended match here", "note"); 426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // FIXME: If we wanted to be really friendly we would show why the match 428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // failed, as it can be hard to spot simple one character differences. 429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===// 433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Check Strings. 434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===// 435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// CheckString - This is a check that we found in the input file. 437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstruct CheckString { 438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// Pat - The pattern to match. 439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Pattern Pat; 44019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// Loc - The location in the match file that the check string was specified. 442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SMLoc Loc; 44319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed 445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// to a CHECK: directive. 446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman bool IsCheckNext; 44719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// NotStrings - These are all of the strings that are disallowed from 449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// occurring between this match string and the previous one (or start of 450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// file). 451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::vector<std::pair<SMLoc, Pattern> > NotStrings; 45219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckString(const Pattern &P, SMLoc L, bool isCheckNext) 454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman : Pat(P), Loc(L), IsCheckNext(isCheckNext) {} 455894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}; 456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified 458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// memory buffer, free it, and return a new one. 459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { 460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SmallString<128> NewFile; 461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman NewFile.reserve(MB->getBufferSize()); 46219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd(); 464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Ptr != End; ++Ptr) { 46519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Eliminate trailing dosish \r. 46619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { 46719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman continue; 46819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 46919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If C is not a horizontal whitespace, skip it. 471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (*Ptr != ' ' && *Ptr != '\t') { 472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman NewFile.push_back(*Ptr); 473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 47519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Otherwise, add one space and advance over neighboring space. 477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman NewFile.push_back(' '); 478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman while (Ptr+1 != End && 479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman (Ptr[1] == ' ' || Ptr[1] == '\t')) 480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman ++Ptr; 481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 48219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Free the old buffer and return a new one. 484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman MemoryBuffer *MB2 = 485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); 48619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman delete MB; 488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return MB2; 489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// ReadCheckFile - Read the check file, which specifies the sequence of 493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// expected strings. The strings are added to the CheckStrings vector. 494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic bool ReadCheckFile(SourceMgr &SM, 495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::vector<CheckString> &CheckStrings) { 496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Open the check file, and tell SourceMgr about it. 49719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OwningPtr<MemoryBuffer> File; 49819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (error_code ec = 49919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) { 50019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman errs() << "Could not open check file '" << CheckFilename << "': " 50119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman << ec.message() << '\n'; 502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 50419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MemoryBuffer *F = File.take(); 50519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If we want to canonicalize whitespace, strip excess whitespace from the 507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // buffer containing the CHECK lines. 508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!NoCanonicalizeWhiteSpace) 509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman F = CanonicalizeInputFile(F); 51019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.AddNewSourceBuffer(F, SMLoc()); 512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Find all instances of CheckPrefix followed by : in the file. 514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef Buffer = F->getBuffer(); 515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::vector<std::pair<SMLoc, Pattern> > NotMatches; 51719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman while (1) { 519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // See if Prefix occurs in the memory buffer. 520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(Buffer.find(CheckPrefix)); 52119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If we didn't find a match, we're done. 523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Buffer.empty()) 524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman break; 52519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const char *CheckPrefixStart = Buffer.data(); 52719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // When we find a check prefix, keep track of whether we find CHECK: or 529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // CHECK-NEXT: 530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman bool IsCheckNext = false, IsCheckNot = false; 53119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Verify that the : is present after the prefix. 533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Buffer[CheckPrefix.size()] == ':') { 534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(CheckPrefix.size()+1); 535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } else if (Buffer.size() > CheckPrefix.size()+6 && 536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) { 537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(CheckPrefix.size()+7); 538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman IsCheckNext = true; 539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } else if (Buffer.size() > CheckPrefix.size()+5 && 540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) { 541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(CheckPrefix.size()+6); 542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman IsCheckNot = true; 543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } else { 544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(1); 545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 54719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Okay, we found the prefix, yay. Remember the rest of the line, but 549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // ignore leading and trailing whitespace. 550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); 55119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Scan ahead to the end of line. 553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t EOL = Buffer.find_first_of("\n\r"); 554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Remember the location of the start of the pattern, for diagnostics. 556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); 557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Parse the pattern. 559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Pattern P; 560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (P.ParsePattern(Buffer.substr(0, EOL), SM)) 561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 56219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(EOL); 564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 56519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Verify that CHECK-NEXT lines have at least one CHECK line before them. 567894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (IsCheckNext && CheckStrings.empty()) { 568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), 569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "found '"+CheckPrefix+"-NEXT:' without previous '"+ 570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckPrefix+ ": line", "error"); 571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 57319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Handle CHECK-NOT. 575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (IsCheckNot) { 576894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()), 577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman P)); 578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman continue; 579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 58019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 58119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 582894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Okay, add the string we captured to the output vector and move on. 583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckStrings.push_back(CheckString(P, 584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PatternLoc, 585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman IsCheckNext)); 586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::swap(NotMatches, CheckStrings.back().NotStrings); 587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 58819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 58919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Add an EOF pattern for any trailing CHECK-NOTs. 59019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!NotMatches.empty()) { 59119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman CheckStrings.push_back(CheckString(Pattern(true), 59219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SMLoc::getFromPointer(Buffer.data()), 59319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman false)); 59419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman std::swap(NotMatches, CheckStrings.back().NotStrings); 59519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 59619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (CheckStrings.empty()) { 598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman errs() << "error: no check strings found with prefix '" << CheckPrefix 599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman << ":'\n"; 600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 60219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return false; 604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, 607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef Buffer, 608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringMap<StringRef> &VariableTable) { 609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Otherwise, we have an error, emit an error message. 610894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(CheckStr.Loc, "expected string not found in input", 611894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "error"); 61219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Print the "scanning from here" line. If the current position is at the 614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // end of a line, advance to the start of the next line. 615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r")); 61619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here", 618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "note"); 619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Allow the pattern to print additional information if desired. 621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckStr.Pat.PrintFailureInfo(SM, Buffer, VariableTable); 622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 623894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// CountNumNewlinesBetween - Count the number of newlines in the specified 625894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// range. 626894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic unsigned CountNumNewlinesBetween(StringRef Range) { 627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman unsigned NumNewLines = 0; 628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman while (1) { 629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Scan for newline. 630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Range = Range.substr(Range.find_first_of("\n\r")); 631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Range.empty()) return NumNewLines; 63219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 633894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman ++NumNewLines; 63419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Handle \n\r and \r\n as a single newline. 636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Range.size() > 1 && 637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman (Range[1] == '\n' || Range[1] == '\r') && 638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman (Range[0] != Range[1])) 639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Range = Range.substr(1); 640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Range = Range.substr(1); 641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanint main(int argc, char **argv) { 645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman sys::PrintStackTraceOnErrorSignal(); 646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PrettyStackTraceProgram X(argc, argv); 647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman cl::ParseCommandLineOptions(argc, argv); 648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SourceMgr SM; 65019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Read the expected strings from the check file. 652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman std::vector<CheckString> CheckStrings; 653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (ReadCheckFile(SM, CheckStrings)) 654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return 2; 655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Open the file to check and add it to SourceMgr. 65719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OwningPtr<MemoryBuffer> File; 65819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (error_code ec = 65919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { 66019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman errs() << "Could not open input file '" << InputFilename << "': " 66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman << ec.message() << '\n'; 662894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return true; 663894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 66419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MemoryBuffer *F = File.take(); 66519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 66619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (F->getBufferSize() == 0) { 66719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 66819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return 1; 66919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 670894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Remove duplicate spaces in the input file if requested. 672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!NoCanonicalizeWhiteSpace) 673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman F = CanonicalizeInputFile(F); 67419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.AddNewSourceBuffer(F, SMLoc()); 67619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman /// VariableTable - This holds all the current filecheck variables. 678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringMap<StringRef> VariableTable; 67919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Check that we have all of the expected strings, in order, in the input 681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // file. 682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef Buffer = F->getBuffer(); 68319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 684894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const char *LastMatch = Buffer.data(); 68519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 686894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) { 687894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman const CheckString &CheckStr = CheckStrings[StrNo]; 68819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef SearchFrom = Buffer; 69019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Find StrNo in the file. 692894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t MatchLen = 0; 69319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman size_t MatchPos = CheckStr.Pat.Match(Buffer, MatchLen, VariableTable); 69419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Buffer = Buffer.substr(MatchPos); 69519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 696894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If we didn't find a match, reject the input. 69719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (MatchPos == StringRef::npos) { 698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable); 699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return 1; 700894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 701894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch); 703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If this check is a "CHECK-NEXT", verify that the previous match was on 705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // the previous line (i.e. that there is one newline between them). 706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (CheckStr.IsCheckNext) { 707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Count the number of newlines between the previous match and this one. 708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman assert(LastMatch != F->getBufferStart() && 709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "CHECK-NEXT can't be the first check in a file"); 710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion); 712894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (NumNewLines == 0) { 713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(CheckStr.Loc, 714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckPrefix+"-NEXT: is on the same line as previous match", 715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "error"); 716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), 717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "'next' match was here", "note"); 718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(LastMatch), 719894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "previous match was here", "note"); 720894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return 1; 721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 72219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (NumNewLines != 1) { 724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(CheckStr.Loc, 725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckPrefix+ 726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "-NEXT: is not on the line after the previous match", 727894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "error"); 728894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), 729894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "'next' match was here", "note"); 730894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(LastMatch), 731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman "previous match was here", "note"); 732894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return 1; 733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 73519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // If this match had "not strings", verify that they don't exist in the 737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // skipped region. 738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size(); 739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman ChunkNo != e; ++ChunkNo) { 740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t MatchLen = 0; 741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion, 742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman MatchLen, 743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman VariableTable); 744894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (Pos == StringRef::npos) continue; 74519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos), 747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckPrefix+"-NOT: string occurred!", "error"); 748894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first, 749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman CheckPrefix+"-NOT: pattern specified here", "note"); 750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return 1; 751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 75219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // Otherwise, everything is good. Step over the matched text and remember 755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman // the position after the match as the end of the last match. 756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Buffer = Buffer.substr(MatchLen); 757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman LastMatch = Buffer.data(); 758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 75919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return 0; 761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 762