blob: 199e95fd668db01bd848fa35cd2539f536d96a62 [file] [log] [blame]
Chris Lattner81cb8ca2009-07-08 18:44:05 +00001//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// FileCheck does a line-by line check of a file that validates whether it
11// contains the expected content. This is useful for regression tests etc.
12//
13// This program exits with an error status of 2 on error, exit status of 0 if
14// the file matched the expected contents, and exit status of 1 if it did not
15// contain the expected contents.
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/Support/CommandLine.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/PrettyStackTrace.h"
Chris Lattner52870082009-09-24 21:47:32 +000022#include "llvm/Support/Regex.h"
Chris Lattner81cb8ca2009-07-08 18:44:05 +000023#include "llvm/Support/SourceMgr.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/System/Signals.h"
26using namespace llvm;
27
28static cl::opt<std::string>
29CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
30
31static cl::opt<std::string>
32InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
33 cl::init("-"), cl::value_desc("filename"));
34
35static cl::opt<std::string>
36CheckPrefix("check-prefix", cl::init("CHECK"),
37 cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
38
Chris Lattner88a7e9e2009-07-11 18:58:15 +000039static cl::opt<bool>
40NoCanonicalizeWhiteSpace("strict-whitespace",
41 cl::desc("Do not treat all horizontal whitespace as equivalent"));
42
Chris Lattnera29703e2009-09-24 20:39:13 +000043//===----------------------------------------------------------------------===//
44// Pattern Handling Code.
45//===----------------------------------------------------------------------===//
46
Chris Lattnerbfa2eed2009-09-25 06:32:47 +000047class PatternChunk {
48 StringRef Str;
49 bool isRegEx;
50public:
51 PatternChunk(StringRef S, bool isRE) : Str(S), isRegEx(isRE) {}
52
53
54 size_t Match(StringRef Buffer, size_t &MatchLen) const {
55 if (!isRegEx) {
56 // Fixed string match.
57 MatchLen = Str.size();
58 return Buffer.find(Str);
59 }
60
61 // Regex match.
62 SmallVector<StringRef, 4> MatchInfo;
63 if (!Regex(Str, Regex::Sub).match(Buffer, &MatchInfo))
64 return StringRef::npos;
65
66 // Successful regex match.
67 assert(!MatchInfo.empty() && "Didn't get any match");
68 StringRef FullMatch = MatchInfo[0];
69
70 MatchLen = FullMatch.size();
71 return FullMatch.data()-Buffer.data();
72 }
73
74};
75
Chris Lattner9fc66782009-09-24 20:25:55 +000076class Pattern {
Chris Lattner52870082009-09-24 21:47:32 +000077 /// Chunks - The pattern chunks to match. If the bool is false, it is a fixed
78 /// string match, if it is true, it is a regex match.
Chris Lattnerbfa2eed2009-09-25 06:32:47 +000079 SmallVector<PatternChunk, 4> Chunks;
Chris Lattner9fc66782009-09-24 20:25:55 +000080public:
81
Chris Lattnera29703e2009-09-24 20:39:13 +000082 Pattern() { }
83
84 bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
Chris Lattner9fc66782009-09-24 20:25:55 +000085
86 /// Match - Match the pattern string against the input buffer Buffer. This
87 /// returns the position that is matched or npos if there is no match. If
88 /// there is a match, the size of the matched string is returned in MatchLen.
Chris Lattner52870082009-09-24 21:47:32 +000089 size_t Match(StringRef Buffer, size_t &MatchLen) const;
Chris Lattner9fc66782009-09-24 20:25:55 +000090};
91
Chris Lattnera29703e2009-09-24 20:39:13 +000092bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
93 // Ignore trailing whitespace.
94 while (!PatternStr.empty() &&
95 (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
96 PatternStr = PatternStr.substr(0, PatternStr.size()-1);
97
98 // Check that there is something on the line.
99 if (PatternStr.empty()) {
100 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
101 "found empty check string with prefix '"+CheckPrefix+":'",
102 "error");
103 return true;
104 }
Chris Lattner52870082009-09-24 21:47:32 +0000105
106 // Scan the pattern to break it into regex and non-regex pieces.
107 while (!PatternStr.empty()) {
108 // Handle fixed string matches.
109 if (PatternStr.size() < 2 ||
110 PatternStr[0] != '{' || PatternStr[1] != '{') {
111 // Find the end, which is the start of the next regex.
112 size_t FixedMatchEnd = PatternStr.find("{{");
113
Chris Lattnerbfa2eed2009-09-25 06:32:47 +0000114 Chunks.push_back(PatternChunk(PatternStr.substr(0, FixedMatchEnd),false));
Chris Lattner52870082009-09-24 21:47:32 +0000115 PatternStr = PatternStr.substr(FixedMatchEnd);
116 continue;
117 }
118
119 // Otherwise, this is the start of a regex match. Scan for the }}.
120 size_t End = PatternStr.find("}}");
121 if (End == StringRef::npos) {
122 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
123 "found start of regex string with no end '}}'", "error");
124 return true;
125 }
126
127 Regex R(PatternStr.substr(2, End-2));
128 std::string Error;
129 if (!R.isValid(Error)) {
130 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()+2),
131 "invalid regex: " + Error, "error");
132 return true;
133 }
134
Chris Lattnerbfa2eed2009-09-25 06:32:47 +0000135 Chunks.push_back(PatternChunk(PatternStr.substr(2, End-2), true));
Chris Lattner52870082009-09-24 21:47:32 +0000136 PatternStr = PatternStr.substr(End+2);
137 }
Chris Lattneradea46e2009-09-24 20:45:07 +0000138
Chris Lattnera29703e2009-09-24 20:39:13 +0000139 return false;
140}
141
Chris Lattner52870082009-09-24 21:47:32 +0000142/// Match - Match the pattern string against the input buffer Buffer. This
143/// returns the position that is matched or npos if there is no match. If
144/// there is a match, the size of the matched string is returned in MatchLen.
145size_t Pattern::Match(StringRef Buffer, size_t &MatchLen) const {
146 size_t FirstMatch = StringRef::npos;
147 MatchLen = 0;
148
Chris Lattner52870082009-09-24 21:47:32 +0000149 while (!Buffer.empty()) {
150 StringRef MatchAttempt = Buffer;
151
152 unsigned ChunkNo = 0, e = Chunks.size();
153 for (; ChunkNo != e; ++ChunkNo) {
Chris Lattnerbfa2eed2009-09-25 06:32:47 +0000154 size_t ThisMatch, ThisLength = StringRef::npos;
155 ThisMatch = Chunks[ChunkNo].Match(MatchAttempt, ThisLength);
Chris Lattner52870082009-09-24 21:47:32 +0000156
157 // Otherwise, what we do depends on if this is the first match or not. If
158 // this is the first match, it doesn't match to match at the start of
159 // MatchAttempt.
160 if (ChunkNo == 0) {
161 // If the first match fails then this pattern will never match in
162 // Buffer.
163 if (ThisMatch == StringRef::npos)
164 return ThisMatch;
165
166 FirstMatch = ThisMatch;
167 MatchAttempt = MatchAttempt.substr(FirstMatch);
168 ThisMatch = 0;
169 }
170
171 // If this chunk didn't match, then the entire pattern didn't match from
172 // FirstMatch, try later in the buffer.
173 if (ThisMatch == StringRef::npos)
174 break;
175
176 // Ok, if the match didn't match at the beginning of MatchAttempt, then we
177 // have something like "ABC{{DEF}} and something was in-between. Reject
178 // the match.
179 if (ThisMatch != 0)
180 break;
181
182 // Otherwise, match the string and move to the next chunk.
183 MatchLen += ThisLength;
184 MatchAttempt = MatchAttempt.substr(ThisLength);
185 }
186
187 // If the whole thing matched, we win.
188 if (ChunkNo == e)
189 return FirstMatch;
190
191 // Otherwise, try matching again after FirstMatch to see if this pattern
192 // matches later in the buffer.
193 Buffer = Buffer.substr(FirstMatch+1);
194 }
195
196 // If we ran out of stuff to scan, then we didn't match.
197 return StringRef::npos;
198}
199
Chris Lattnera29703e2009-09-24 20:39:13 +0000200
201//===----------------------------------------------------------------------===//
202// Check Strings.
203//===----------------------------------------------------------------------===//
Chris Lattner9fc66782009-09-24 20:25:55 +0000204
205/// CheckString - This is a check that we found in the input file.
206struct CheckString {
207 /// Pat - The pattern to match.
208 Pattern Pat;
Chris Lattner207e1bc2009-08-15 17:41:04 +0000209
210 /// Loc - The location in the match file that the check string was specified.
211 SMLoc Loc;
212
Chris Lattner5dafafd2009-08-15 18:32:21 +0000213 /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
214 /// to a CHECK: directive.
215 bool IsCheckNext;
216
Chris Lattnerf15380b2009-09-20 22:35:26 +0000217 /// NotStrings - These are all of the strings that are disallowed from
218 /// occurring between this match string and the previous one (or start of
219 /// file).
Chris Lattnera29703e2009-09-24 20:39:13 +0000220 std::vector<std::pair<SMLoc, Pattern> > NotStrings;
Chris Lattnerf15380b2009-09-20 22:35:26 +0000221
Chris Lattner9fc66782009-09-24 20:25:55 +0000222 CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
223 : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
Chris Lattner207e1bc2009-08-15 17:41:04 +0000224};
225
Chris Lattneradea46e2009-09-24 20:45:07 +0000226/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
227/// memory buffer, free it, and return a new one.
228static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
229 SmallVector<char, 16> NewFile;
230 NewFile.reserve(MB->getBufferSize());
231
232 for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
233 Ptr != End; ++Ptr) {
234 // If C is not a horizontal whitespace, skip it.
235 if (*Ptr != ' ' && *Ptr != '\t') {
236 NewFile.push_back(*Ptr);
237 continue;
238 }
239
240 // Otherwise, add one space and advance over neighboring space.
241 NewFile.push_back(' ');
242 while (Ptr+1 != End &&
243 (Ptr[1] == ' ' || Ptr[1] == '\t'))
244 ++Ptr;
245 }
246
247 // Free the old buffer and return a new one.
248 MemoryBuffer *MB2 =
249 MemoryBuffer::getMemBufferCopy(NewFile.data(),
250 NewFile.data() + NewFile.size(),
251 MB->getBufferIdentifier());
252
253 delete MB;
254 return MB2;
255}
256
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000257
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000258/// ReadCheckFile - Read the check file, which specifies the sequence of
259/// expected strings. The strings are added to the CheckStrings vector.
260static bool ReadCheckFile(SourceMgr &SM,
Chris Lattner207e1bc2009-08-15 17:41:04 +0000261 std::vector<CheckString> &CheckStrings) {
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000262 // Open the check file, and tell SourceMgr about it.
263 std::string ErrorStr;
264 MemoryBuffer *F =
265 MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
266 if (F == 0) {
267 errs() << "Could not open check file '" << CheckFilename << "': "
268 << ErrorStr << '\n';
269 return true;
270 }
Chris Lattneradea46e2009-09-24 20:45:07 +0000271
272 // If we want to canonicalize whitespace, strip excess whitespace from the
273 // buffer containing the CHECK lines.
274 if (!NoCanonicalizeWhiteSpace)
275 F = CanonicalizeInputFile(F);
276
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000277 SM.AddNewSourceBuffer(F, SMLoc());
278
Chris Lattnerd7e25052009-08-15 18:00:42 +0000279 // Find all instances of CheckPrefix followed by : in the file.
Chris Lattner96077032009-09-20 22:11:44 +0000280 StringRef Buffer = F->getBuffer();
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000281
Chris Lattnera29703e2009-09-24 20:39:13 +0000282 std::vector<std::pair<SMLoc, Pattern> > NotMatches;
Chris Lattnerf15380b2009-09-20 22:35:26 +0000283
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000284 while (1) {
285 // See if Prefix occurs in the memory buffer.
Chris Lattner96077032009-09-20 22:11:44 +0000286 Buffer = Buffer.substr(Buffer.find(CheckPrefix));
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000287
288 // If we didn't find a match, we're done.
Chris Lattner96077032009-09-20 22:11:44 +0000289 if (Buffer.empty())
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000290 break;
291
Chris Lattner96077032009-09-20 22:11:44 +0000292 const char *CheckPrefixStart = Buffer.data();
Chris Lattner5dafafd2009-08-15 18:32:21 +0000293
294 // When we find a check prefix, keep track of whether we find CHECK: or
295 // CHECK-NEXT:
Chris Lattnerf15380b2009-09-20 22:35:26 +0000296 bool IsCheckNext = false, IsCheckNot = false;
Chris Lattner5dafafd2009-08-15 18:32:21 +0000297
Chris Lattnerd7e25052009-08-15 18:00:42 +0000298 // Verify that the : is present after the prefix.
Chris Lattner96077032009-09-20 22:11:44 +0000299 if (Buffer[CheckPrefix.size()] == ':') {
300 Buffer = Buffer.substr(CheckPrefix.size()+1);
Chris Lattner96077032009-09-20 22:11:44 +0000301 } else if (Buffer.size() > CheckPrefix.size()+6 &&
302 memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
303 Buffer = Buffer.substr(CheckPrefix.size()+7);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000304 IsCheckNext = true;
Chris Lattnerf15380b2009-09-20 22:35:26 +0000305 } else if (Buffer.size() > CheckPrefix.size()+5 &&
306 memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
307 Buffer = Buffer.substr(CheckPrefix.size()+6);
308 IsCheckNot = true;
Chris Lattner5dafafd2009-08-15 18:32:21 +0000309 } else {
Chris Lattner96077032009-09-20 22:11:44 +0000310 Buffer = Buffer.substr(1);
Chris Lattnerd7e25052009-08-15 18:00:42 +0000311 continue;
312 }
313
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000314 // Okay, we found the prefix, yay. Remember the rest of the line, but
315 // ignore leading and trailing whitespace.
Chris Lattnerf15380b2009-09-20 22:35:26 +0000316 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000317
318 // Scan ahead to the end of line.
Chris Lattner96077032009-09-20 22:11:44 +0000319 size_t EOL = Buffer.find_first_of("\n\r");
Chris Lattnera29703e2009-09-24 20:39:13 +0000320
321 // Parse the pattern.
322 Pattern P;
323 if (P.ParsePattern(Buffer.substr(0, EOL), SM))
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000324 return true;
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000325
Chris Lattnera29703e2009-09-24 20:39:13 +0000326 Buffer = Buffer.substr(EOL);
327
Chris Lattnerf15380b2009-09-20 22:35:26 +0000328
Chris Lattner5dafafd2009-08-15 18:32:21 +0000329 // Verify that CHECK-NEXT lines have at least one CHECK line before them.
330 if (IsCheckNext && CheckStrings.empty()) {
331 SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
332 "found '"+CheckPrefix+"-NEXT:' without previous '"+
333 CheckPrefix+ ": line", "error");
334 return true;
335 }
336
Chris Lattnera29703e2009-09-24 20:39:13 +0000337 // Handle CHECK-NOT.
338 if (IsCheckNot) {
339 NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
340 P));
341 continue;
342 }
343
Chris Lattner9fc66782009-09-24 20:25:55 +0000344
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000345 // Okay, add the string we captured to the output vector and move on.
Chris Lattner9fc66782009-09-24 20:25:55 +0000346 CheckStrings.push_back(CheckString(P,
Chris Lattner96077032009-09-20 22:11:44 +0000347 SMLoc::getFromPointer(Buffer.data()),
Chris Lattner5dafafd2009-08-15 18:32:21 +0000348 IsCheckNext));
Chris Lattnerf15380b2009-09-20 22:35:26 +0000349 std::swap(NotMatches, CheckStrings.back().NotStrings);
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000350 }
351
352 if (CheckStrings.empty()) {
Chris Lattnerd7e25052009-08-15 18:00:42 +0000353 errs() << "error: no check strings found with prefix '" << CheckPrefix
354 << ":'\n";
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000355 return true;
356 }
357
Chris Lattnerf15380b2009-09-20 22:35:26 +0000358 if (!NotMatches.empty()) {
359 errs() << "error: '" << CheckPrefix
360 << "-NOT:' not supported after last check line.\n";
361 return true;
362 }
363
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000364 return false;
365}
366
Chris Lattner5dafafd2009-08-15 18:32:21 +0000367static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
Chris Lattner96077032009-09-20 22:11:44 +0000368 StringRef Buffer) {
Chris Lattner5dafafd2009-08-15 18:32:21 +0000369 // Otherwise, we have an error, emit an error message.
370 SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
371 "error");
372
373 // Print the "scanning from here" line. If the current position is at the
374 // end of a line, advance to the start of the next line.
Chris Lattner96077032009-09-20 22:11:44 +0000375 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
Chris Lattner5dafafd2009-08-15 18:32:21 +0000376
Chris Lattner96077032009-09-20 22:11:44 +0000377 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
Chris Lattner5dafafd2009-08-15 18:32:21 +0000378 "note");
379}
380
Chris Lattner3711b7a2009-09-20 22:42:44 +0000381/// CountNumNewlinesBetween - Count the number of newlines in the specified
382/// range.
383static unsigned CountNumNewlinesBetween(StringRef Range) {
Chris Lattner5dafafd2009-08-15 18:32:21 +0000384 unsigned NumNewLines = 0;
Chris Lattner3711b7a2009-09-20 22:42:44 +0000385 while (1) {
Chris Lattner5dafafd2009-08-15 18:32:21 +0000386 // Scan for newline.
Chris Lattner3711b7a2009-09-20 22:42:44 +0000387 Range = Range.substr(Range.find_first_of("\n\r"));
388 if (Range.empty()) return NumNewLines;
Chris Lattner5dafafd2009-08-15 18:32:21 +0000389
390 ++NumNewLines;
391
392 // Handle \n\r and \r\n as a single newline.
Chris Lattner3711b7a2009-09-20 22:42:44 +0000393 if (Range.size() > 1 &&
394 (Range[1] == '\n' || Range[1] == '\r') &&
395 (Range[0] != Range[1]))
396 Range = Range.substr(1);
397 Range = Range.substr(1);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000398 }
Chris Lattner5dafafd2009-08-15 18:32:21 +0000399}
400
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000401int main(int argc, char **argv) {
402 sys::PrintStackTraceOnErrorSignal();
403 PrettyStackTraceProgram X(argc, argv);
404 cl::ParseCommandLineOptions(argc, argv);
405
406 SourceMgr SM;
407
408 // Read the expected strings from the check file.
Chris Lattner207e1bc2009-08-15 17:41:04 +0000409 std::vector<CheckString> CheckStrings;
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000410 if (ReadCheckFile(SM, CheckStrings))
411 return 2;
412
413 // Open the file to check and add it to SourceMgr.
414 std::string ErrorStr;
415 MemoryBuffer *F =
416 MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
417 if (F == 0) {
418 errs() << "Could not open input file '" << InputFilename << "': "
419 << ErrorStr << '\n';
420 return true;
421 }
Chris Lattner88a7e9e2009-07-11 18:58:15 +0000422
423 // Remove duplicate spaces in the input file if requested.
424 if (!NoCanonicalizeWhiteSpace)
425 F = CanonicalizeInputFile(F);
426
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000427 SM.AddNewSourceBuffer(F, SMLoc());
428
429 // Check that we have all of the expected strings, in order, in the input
430 // file.
Chris Lattner96077032009-09-20 22:11:44 +0000431 StringRef Buffer = F->getBuffer();
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000432
Chris Lattnerf15380b2009-09-20 22:35:26 +0000433 const char *LastMatch = Buffer.data();
434
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000435 for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
Chris Lattner207e1bc2009-08-15 17:41:04 +0000436 const CheckString &CheckStr = CheckStrings[StrNo];
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000437
Chris Lattner96077032009-09-20 22:11:44 +0000438 StringRef SearchFrom = Buffer;
439
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000440 // Find StrNo in the file.
Chris Lattner9fc66782009-09-24 20:25:55 +0000441 size_t MatchLen = 0;
442 Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000443
Chris Lattner5dafafd2009-08-15 18:32:21 +0000444 // If we didn't find a match, reject the input.
Chris Lattner96077032009-09-20 22:11:44 +0000445 if (Buffer.empty()) {
446 PrintCheckFailed(SM, CheckStr, SearchFrom);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000447 return 1;
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000448 }
Chris Lattner3711b7a2009-09-20 22:42:44 +0000449
450 StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
451
Chris Lattner5dafafd2009-08-15 18:32:21 +0000452 // If this check is a "CHECK-NEXT", verify that the previous match was on
453 // the previous line (i.e. that there is one newline between them).
454 if (CheckStr.IsCheckNext) {
455 // Count the number of newlines between the previous match and this one.
Chris Lattnerf15380b2009-09-20 22:35:26 +0000456 assert(LastMatch != F->getBufferStart() &&
457 "CHECK-NEXT can't be the first check in a file");
Chris Lattner5dafafd2009-08-15 18:32:21 +0000458
Chris Lattner3711b7a2009-09-20 22:42:44 +0000459 unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000460 if (NumNewLines == 0) {
Chris Lattner0b2353f2009-08-16 02:22:31 +0000461 SM.PrintMessage(CheckStr.Loc,
Chris Lattner5dafafd2009-08-15 18:32:21 +0000462 CheckPrefix+"-NEXT: is on the same line as previous match",
463 "error");
Chris Lattner96077032009-09-20 22:11:44 +0000464 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
Chris Lattner0b2353f2009-08-16 02:22:31 +0000465 "'next' match was here", "note");
Chris Lattner5dafafd2009-08-15 18:32:21 +0000466 SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
467 "previous match was here", "note");
468 return 1;
469 }
470
471 if (NumNewLines != 1) {
Chris Lattner0b2353f2009-08-16 02:22:31 +0000472 SM.PrintMessage(CheckStr.Loc,
Chris Lattner5dafafd2009-08-15 18:32:21 +0000473 CheckPrefix+
474 "-NEXT: is not on the line after the previous match",
475 "error");
Chris Lattner96077032009-09-20 22:11:44 +0000476 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
Chris Lattner0b2353f2009-08-16 02:22:31 +0000477 "'next' match was here", "note");
Chris Lattner5dafafd2009-08-15 18:32:21 +0000478 SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
479 "previous match was here", "note");
480 return 1;
481 }
482 }
Chris Lattnerf15380b2009-09-20 22:35:26 +0000483
484 // If this match had "not strings", verify that they don't exist in the
485 // skipped region.
Chris Lattner52870082009-09-24 21:47:32 +0000486 for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size(); ChunkNo != e; ++ChunkNo) {
Chris Lattnera29703e2009-09-24 20:39:13 +0000487 size_t MatchLen = 0;
Chris Lattner52870082009-09-24 21:47:32 +0000488 size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion, MatchLen);
Chris Lattnerf15380b2009-09-20 22:35:26 +0000489 if (Pos == StringRef::npos) continue;
490
491 SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
492 CheckPrefix+"-NOT: string occurred!", "error");
Chris Lattner52870082009-09-24 21:47:32 +0000493 SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first,
Chris Lattnerf15380b2009-09-20 22:35:26 +0000494 CheckPrefix+"-NOT: pattern specified here", "note");
495 return 1;
496 }
497
Chris Lattner5dafafd2009-08-15 18:32:21 +0000498
Chris Lattner81115762009-09-21 02:30:42 +0000499 // Otherwise, everything is good. Step over the matched text and remember
500 // the position after the match as the end of the last match.
Chris Lattner9fc66782009-09-24 20:25:55 +0000501 Buffer = Buffer.substr(MatchLen);
Chris Lattner81115762009-09-21 02:30:42 +0000502 LastMatch = Buffer.data();
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000503 }
504
505 return 0;
506}