blob: 1f79b92e9d04e0177790e8e67ea293d8d12152bb [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
Chris Lattnerbfa2eed2009-09-25 06:32:47 +000053 size_t Match(StringRef Buffer, size_t &MatchLen) const {
54 if (!isRegEx) {
55 // Fixed string match.
56 MatchLen = Str.size();
57 return Buffer.find(Str);
58 }
59
60 // Regex match.
61 SmallVector<StringRef, 4> MatchInfo;
Chris Lattnerd9485dd2009-09-25 06:47:09 +000062 if (!Regex(Str, Regex::Sub|Regex::Newline).match(Buffer, &MatchInfo))
Chris Lattnerbfa2eed2009-09-25 06:32:47 +000063 return StringRef::npos;
64
65 // Successful regex match.
66 assert(!MatchInfo.empty() && "Didn't get any match");
67 StringRef FullMatch = MatchInfo[0];
68
69 MatchLen = FullMatch.size();
70 return FullMatch.data()-Buffer.data();
71 }
Chris Lattnerbfa2eed2009-09-25 06:32:47 +000072};
73
Chris Lattner9fc66782009-09-24 20:25:55 +000074class Pattern {
Chris Lattner52870082009-09-24 21:47:32 +000075 /// Chunks - The pattern chunks to match. If the bool is false, it is a fixed
76 /// string match, if it is true, it is a regex match.
Chris Lattnerbfa2eed2009-09-25 06:32:47 +000077 SmallVector<PatternChunk, 4> Chunks;
Chris Lattner9fc66782009-09-24 20:25:55 +000078public:
79
Chris Lattnera29703e2009-09-24 20:39:13 +000080 Pattern() { }
81
82 bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
Chris Lattner9fc66782009-09-24 20:25:55 +000083
84 /// Match - Match the pattern string against the input buffer Buffer. This
85 /// returns the position that is matched or npos if there is no match. If
86 /// there is a match, the size of the matched string is returned in MatchLen.
Chris Lattner52870082009-09-24 21:47:32 +000087 size_t Match(StringRef Buffer, size_t &MatchLen) const;
Chris Lattner9fc66782009-09-24 20:25:55 +000088};
89
Chris Lattnera29703e2009-09-24 20:39:13 +000090bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
91 // Ignore trailing whitespace.
92 while (!PatternStr.empty() &&
93 (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
94 PatternStr = PatternStr.substr(0, PatternStr.size()-1);
95
96 // Check that there is something on the line.
97 if (PatternStr.empty()) {
98 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
99 "found empty check string with prefix '"+CheckPrefix+":'",
100 "error");
101 return true;
102 }
Chris Lattner52870082009-09-24 21:47:32 +0000103
104 // Scan the pattern to break it into regex and non-regex pieces.
105 while (!PatternStr.empty()) {
106 // Handle fixed string matches.
107 if (PatternStr.size() < 2 ||
108 PatternStr[0] != '{' || PatternStr[1] != '{') {
109 // Find the end, which is the start of the next regex.
110 size_t FixedMatchEnd = PatternStr.find("{{");
111
Chris Lattnerbfa2eed2009-09-25 06:32:47 +0000112 Chunks.push_back(PatternChunk(PatternStr.substr(0, FixedMatchEnd),false));
Chris Lattner52870082009-09-24 21:47:32 +0000113 PatternStr = PatternStr.substr(FixedMatchEnd);
114 continue;
115 }
116
117 // Otherwise, this is the start of a regex match. Scan for the }}.
118 size_t End = PatternStr.find("}}");
119 if (End == StringRef::npos) {
120 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
121 "found start of regex string with no end '}}'", "error");
122 return true;
123 }
124
125 Regex R(PatternStr.substr(2, End-2));
126 std::string Error;
127 if (!R.isValid(Error)) {
128 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()+2),
129 "invalid regex: " + Error, "error");
130 return true;
131 }
132
Chris Lattnerbfa2eed2009-09-25 06:32:47 +0000133 Chunks.push_back(PatternChunk(PatternStr.substr(2, End-2), true));
Chris Lattner52870082009-09-24 21:47:32 +0000134 PatternStr = PatternStr.substr(End+2);
135 }
Chris Lattneradea46e2009-09-24 20:45:07 +0000136
Chris Lattnera29703e2009-09-24 20:39:13 +0000137 return false;
138}
139
Chris Lattner52870082009-09-24 21:47:32 +0000140/// Match - Match the pattern string against the input buffer Buffer. This
141/// returns the position that is matched or npos if there is no match. If
142/// there is a match, the size of the matched string is returned in MatchLen.
143size_t Pattern::Match(StringRef Buffer, size_t &MatchLen) const {
144 size_t FirstMatch = StringRef::npos;
145 MatchLen = 0;
146
Chris Lattner52870082009-09-24 21:47:32 +0000147 while (!Buffer.empty()) {
148 StringRef MatchAttempt = Buffer;
149
150 unsigned ChunkNo = 0, e = Chunks.size();
151 for (; ChunkNo != e; ++ChunkNo) {
Chris Lattnerbfa2eed2009-09-25 06:32:47 +0000152 size_t ThisMatch, ThisLength = StringRef::npos;
153 ThisMatch = Chunks[ChunkNo].Match(MatchAttempt, ThisLength);
Chris Lattner52870082009-09-24 21:47:32 +0000154
155 // Otherwise, what we do depends on if this is the first match or not. If
156 // this is the first match, it doesn't match to match at the start of
157 // MatchAttempt.
158 if (ChunkNo == 0) {
159 // If the first match fails then this pattern will never match in
160 // Buffer.
161 if (ThisMatch == StringRef::npos)
162 return ThisMatch;
163
164 FirstMatch = ThisMatch;
165 MatchAttempt = MatchAttempt.substr(FirstMatch);
166 ThisMatch = 0;
167 }
168
169 // If this chunk didn't match, then the entire pattern didn't match from
170 // FirstMatch, try later in the buffer.
171 if (ThisMatch == StringRef::npos)
172 break;
173
174 // Ok, if the match didn't match at the beginning of MatchAttempt, then we
175 // have something like "ABC{{DEF}} and something was in-between. Reject
176 // the match.
177 if (ThisMatch != 0)
178 break;
179
180 // Otherwise, match the string and move to the next chunk.
181 MatchLen += ThisLength;
182 MatchAttempt = MatchAttempt.substr(ThisLength);
183 }
184
185 // If the whole thing matched, we win.
186 if (ChunkNo == e)
187 return FirstMatch;
188
189 // Otherwise, try matching again after FirstMatch to see if this pattern
190 // matches later in the buffer.
191 Buffer = Buffer.substr(FirstMatch+1);
192 }
193
194 // If we ran out of stuff to scan, then we didn't match.
195 return StringRef::npos;
196}
197
Chris Lattnera29703e2009-09-24 20:39:13 +0000198
199//===----------------------------------------------------------------------===//
200// Check Strings.
201//===----------------------------------------------------------------------===//
Chris Lattner9fc66782009-09-24 20:25:55 +0000202
203/// CheckString - This is a check that we found in the input file.
204struct CheckString {
205 /// Pat - The pattern to match.
206 Pattern Pat;
Chris Lattner207e1bc2009-08-15 17:41:04 +0000207
208 /// Loc - The location in the match file that the check string was specified.
209 SMLoc Loc;
210
Chris Lattner5dafafd2009-08-15 18:32:21 +0000211 /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
212 /// to a CHECK: directive.
213 bool IsCheckNext;
214
Chris Lattnerf15380b2009-09-20 22:35:26 +0000215 /// NotStrings - These are all of the strings that are disallowed from
216 /// occurring between this match string and the previous one (or start of
217 /// file).
Chris Lattnera29703e2009-09-24 20:39:13 +0000218 std::vector<std::pair<SMLoc, Pattern> > NotStrings;
Chris Lattnerf15380b2009-09-20 22:35:26 +0000219
Chris Lattner9fc66782009-09-24 20:25:55 +0000220 CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
221 : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
Chris Lattner207e1bc2009-08-15 17:41:04 +0000222};
223
Chris Lattneradea46e2009-09-24 20:45:07 +0000224/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
225/// memory buffer, free it, and return a new one.
226static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
227 SmallVector<char, 16> NewFile;
228 NewFile.reserve(MB->getBufferSize());
229
230 for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
231 Ptr != End; ++Ptr) {
232 // If C is not a horizontal whitespace, skip it.
233 if (*Ptr != ' ' && *Ptr != '\t') {
234 NewFile.push_back(*Ptr);
235 continue;
236 }
237
238 // Otherwise, add one space and advance over neighboring space.
239 NewFile.push_back(' ');
240 while (Ptr+1 != End &&
241 (Ptr[1] == ' ' || Ptr[1] == '\t'))
242 ++Ptr;
243 }
244
245 // Free the old buffer and return a new one.
246 MemoryBuffer *MB2 =
247 MemoryBuffer::getMemBufferCopy(NewFile.data(),
248 NewFile.data() + NewFile.size(),
249 MB->getBufferIdentifier());
250
251 delete MB;
252 return MB2;
253}
254
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000255
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000256/// ReadCheckFile - Read the check file, which specifies the sequence of
257/// expected strings. The strings are added to the CheckStrings vector.
258static bool ReadCheckFile(SourceMgr &SM,
Chris Lattner207e1bc2009-08-15 17:41:04 +0000259 std::vector<CheckString> &CheckStrings) {
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000260 // Open the check file, and tell SourceMgr about it.
261 std::string ErrorStr;
262 MemoryBuffer *F =
263 MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
264 if (F == 0) {
265 errs() << "Could not open check file '" << CheckFilename << "': "
266 << ErrorStr << '\n';
267 return true;
268 }
Chris Lattneradea46e2009-09-24 20:45:07 +0000269
270 // If we want to canonicalize whitespace, strip excess whitespace from the
271 // buffer containing the CHECK lines.
272 if (!NoCanonicalizeWhiteSpace)
273 F = CanonicalizeInputFile(F);
274
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000275 SM.AddNewSourceBuffer(F, SMLoc());
276
Chris Lattnerd7e25052009-08-15 18:00:42 +0000277 // Find all instances of CheckPrefix followed by : in the file.
Chris Lattner96077032009-09-20 22:11:44 +0000278 StringRef Buffer = F->getBuffer();
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000279
Chris Lattnera29703e2009-09-24 20:39:13 +0000280 std::vector<std::pair<SMLoc, Pattern> > NotMatches;
Chris Lattnerf15380b2009-09-20 22:35:26 +0000281
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000282 while (1) {
283 // See if Prefix occurs in the memory buffer.
Chris Lattner96077032009-09-20 22:11:44 +0000284 Buffer = Buffer.substr(Buffer.find(CheckPrefix));
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000285
286 // If we didn't find a match, we're done.
Chris Lattner96077032009-09-20 22:11:44 +0000287 if (Buffer.empty())
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000288 break;
289
Chris Lattner96077032009-09-20 22:11:44 +0000290 const char *CheckPrefixStart = Buffer.data();
Chris Lattner5dafafd2009-08-15 18:32:21 +0000291
292 // When we find a check prefix, keep track of whether we find CHECK: or
293 // CHECK-NEXT:
Chris Lattnerf15380b2009-09-20 22:35:26 +0000294 bool IsCheckNext = false, IsCheckNot = false;
Chris Lattner5dafafd2009-08-15 18:32:21 +0000295
Chris Lattnerd7e25052009-08-15 18:00:42 +0000296 // Verify that the : is present after the prefix.
Chris Lattner96077032009-09-20 22:11:44 +0000297 if (Buffer[CheckPrefix.size()] == ':') {
298 Buffer = Buffer.substr(CheckPrefix.size()+1);
Chris Lattner96077032009-09-20 22:11:44 +0000299 } else if (Buffer.size() > CheckPrefix.size()+6 &&
300 memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
301 Buffer = Buffer.substr(CheckPrefix.size()+7);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000302 IsCheckNext = true;
Chris Lattnerf15380b2009-09-20 22:35:26 +0000303 } else if (Buffer.size() > CheckPrefix.size()+5 &&
304 memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
305 Buffer = Buffer.substr(CheckPrefix.size()+6);
306 IsCheckNot = true;
Chris Lattner5dafafd2009-08-15 18:32:21 +0000307 } else {
Chris Lattner96077032009-09-20 22:11:44 +0000308 Buffer = Buffer.substr(1);
Chris Lattnerd7e25052009-08-15 18:00:42 +0000309 continue;
310 }
311
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000312 // Okay, we found the prefix, yay. Remember the rest of the line, but
313 // ignore leading and trailing whitespace.
Chris Lattnerf15380b2009-09-20 22:35:26 +0000314 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000315
316 // Scan ahead to the end of line.
Chris Lattner96077032009-09-20 22:11:44 +0000317 size_t EOL = Buffer.find_first_of("\n\r");
Chris Lattnera29703e2009-09-24 20:39:13 +0000318
319 // Parse the pattern.
320 Pattern P;
321 if (P.ParsePattern(Buffer.substr(0, EOL), SM))
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000322 return true;
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000323
Chris Lattnera29703e2009-09-24 20:39:13 +0000324 Buffer = Buffer.substr(EOL);
325
Chris Lattnerf15380b2009-09-20 22:35:26 +0000326
Chris Lattner5dafafd2009-08-15 18:32:21 +0000327 // Verify that CHECK-NEXT lines have at least one CHECK line before them.
328 if (IsCheckNext && CheckStrings.empty()) {
329 SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
330 "found '"+CheckPrefix+"-NEXT:' without previous '"+
331 CheckPrefix+ ": line", "error");
332 return true;
333 }
334
Chris Lattnera29703e2009-09-24 20:39:13 +0000335 // Handle CHECK-NOT.
336 if (IsCheckNot) {
337 NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
338 P));
339 continue;
340 }
341
Chris Lattner9fc66782009-09-24 20:25:55 +0000342
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000343 // Okay, add the string we captured to the output vector and move on.
Chris Lattner9fc66782009-09-24 20:25:55 +0000344 CheckStrings.push_back(CheckString(P,
Chris Lattner96077032009-09-20 22:11:44 +0000345 SMLoc::getFromPointer(Buffer.data()),
Chris Lattner5dafafd2009-08-15 18:32:21 +0000346 IsCheckNext));
Chris Lattnerf15380b2009-09-20 22:35:26 +0000347 std::swap(NotMatches, CheckStrings.back().NotStrings);
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000348 }
349
350 if (CheckStrings.empty()) {
Chris Lattnerd7e25052009-08-15 18:00:42 +0000351 errs() << "error: no check strings found with prefix '" << CheckPrefix
352 << ":'\n";
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000353 return true;
354 }
355
Chris Lattnerf15380b2009-09-20 22:35:26 +0000356 if (!NotMatches.empty()) {
357 errs() << "error: '" << CheckPrefix
358 << "-NOT:' not supported after last check line.\n";
359 return true;
360 }
361
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000362 return false;
363}
364
Chris Lattner5dafafd2009-08-15 18:32:21 +0000365static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
Chris Lattner96077032009-09-20 22:11:44 +0000366 StringRef Buffer) {
Chris Lattner5dafafd2009-08-15 18:32:21 +0000367 // Otherwise, we have an error, emit an error message.
368 SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
369 "error");
370
371 // Print the "scanning from here" line. If the current position is at the
372 // end of a line, advance to the start of the next line.
Chris Lattner96077032009-09-20 22:11:44 +0000373 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
Chris Lattner5dafafd2009-08-15 18:32:21 +0000374
Chris Lattner96077032009-09-20 22:11:44 +0000375 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
Chris Lattner5dafafd2009-08-15 18:32:21 +0000376 "note");
377}
378
Chris Lattner3711b7a2009-09-20 22:42:44 +0000379/// CountNumNewlinesBetween - Count the number of newlines in the specified
380/// range.
381static unsigned CountNumNewlinesBetween(StringRef Range) {
Chris Lattner5dafafd2009-08-15 18:32:21 +0000382 unsigned NumNewLines = 0;
Chris Lattner3711b7a2009-09-20 22:42:44 +0000383 while (1) {
Chris Lattner5dafafd2009-08-15 18:32:21 +0000384 // Scan for newline.
Chris Lattner3711b7a2009-09-20 22:42:44 +0000385 Range = Range.substr(Range.find_first_of("\n\r"));
386 if (Range.empty()) return NumNewLines;
Chris Lattner5dafafd2009-08-15 18:32:21 +0000387
388 ++NumNewLines;
389
390 // Handle \n\r and \r\n as a single newline.
Chris Lattner3711b7a2009-09-20 22:42:44 +0000391 if (Range.size() > 1 &&
392 (Range[1] == '\n' || Range[1] == '\r') &&
393 (Range[0] != Range[1]))
394 Range = Range.substr(1);
395 Range = Range.substr(1);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000396 }
Chris Lattner5dafafd2009-08-15 18:32:21 +0000397}
398
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000399int main(int argc, char **argv) {
400 sys::PrintStackTraceOnErrorSignal();
401 PrettyStackTraceProgram X(argc, argv);
402 cl::ParseCommandLineOptions(argc, argv);
403
404 SourceMgr SM;
405
406 // Read the expected strings from the check file.
Chris Lattner207e1bc2009-08-15 17:41:04 +0000407 std::vector<CheckString> CheckStrings;
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000408 if (ReadCheckFile(SM, CheckStrings))
409 return 2;
410
411 // Open the file to check and add it to SourceMgr.
412 std::string ErrorStr;
413 MemoryBuffer *F =
414 MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
415 if (F == 0) {
416 errs() << "Could not open input file '" << InputFilename << "': "
417 << ErrorStr << '\n';
418 return true;
419 }
Chris Lattner88a7e9e2009-07-11 18:58:15 +0000420
421 // Remove duplicate spaces in the input file if requested.
422 if (!NoCanonicalizeWhiteSpace)
423 F = CanonicalizeInputFile(F);
424
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000425 SM.AddNewSourceBuffer(F, SMLoc());
426
427 // Check that we have all of the expected strings, in order, in the input
428 // file.
Chris Lattner96077032009-09-20 22:11:44 +0000429 StringRef Buffer = F->getBuffer();
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000430
Chris Lattnerf15380b2009-09-20 22:35:26 +0000431 const char *LastMatch = Buffer.data();
432
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000433 for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
Chris Lattner207e1bc2009-08-15 17:41:04 +0000434 const CheckString &CheckStr = CheckStrings[StrNo];
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000435
Chris Lattner96077032009-09-20 22:11:44 +0000436 StringRef SearchFrom = Buffer;
437
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000438 // Find StrNo in the file.
Chris Lattner9fc66782009-09-24 20:25:55 +0000439 size_t MatchLen = 0;
440 Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000441
Chris Lattner5dafafd2009-08-15 18:32:21 +0000442 // If we didn't find a match, reject the input.
Chris Lattner96077032009-09-20 22:11:44 +0000443 if (Buffer.empty()) {
444 PrintCheckFailed(SM, CheckStr, SearchFrom);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000445 return 1;
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000446 }
Chris Lattner3711b7a2009-09-20 22:42:44 +0000447
448 StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
449
Chris Lattner5dafafd2009-08-15 18:32:21 +0000450 // If this check is a "CHECK-NEXT", verify that the previous match was on
451 // the previous line (i.e. that there is one newline between them).
452 if (CheckStr.IsCheckNext) {
453 // Count the number of newlines between the previous match and this one.
Chris Lattnerf15380b2009-09-20 22:35:26 +0000454 assert(LastMatch != F->getBufferStart() &&
455 "CHECK-NEXT can't be the first check in a file");
Chris Lattner5dafafd2009-08-15 18:32:21 +0000456
Chris Lattner3711b7a2009-09-20 22:42:44 +0000457 unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
Chris Lattner5dafafd2009-08-15 18:32:21 +0000458 if (NumNewLines == 0) {
Chris Lattner0b2353f2009-08-16 02:22:31 +0000459 SM.PrintMessage(CheckStr.Loc,
Chris Lattner5dafafd2009-08-15 18:32:21 +0000460 CheckPrefix+"-NEXT: is on the same line as previous match",
461 "error");
Chris Lattner96077032009-09-20 22:11:44 +0000462 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
Chris Lattner0b2353f2009-08-16 02:22:31 +0000463 "'next' match was here", "note");
Chris Lattner5dafafd2009-08-15 18:32:21 +0000464 SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
465 "previous match was here", "note");
466 return 1;
467 }
468
469 if (NumNewLines != 1) {
Chris Lattner0b2353f2009-08-16 02:22:31 +0000470 SM.PrintMessage(CheckStr.Loc,
Chris Lattner5dafafd2009-08-15 18:32:21 +0000471 CheckPrefix+
472 "-NEXT: is not on the line after the previous match",
473 "error");
Chris Lattner96077032009-09-20 22:11:44 +0000474 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
Chris Lattner0b2353f2009-08-16 02:22:31 +0000475 "'next' match was here", "note");
Chris Lattner5dafafd2009-08-15 18:32:21 +0000476 SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
477 "previous match was here", "note");
478 return 1;
479 }
480 }
Chris Lattnerf15380b2009-09-20 22:35:26 +0000481
482 // If this match had "not strings", verify that they don't exist in the
483 // skipped region.
Chris Lattner52870082009-09-24 21:47:32 +0000484 for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size(); ChunkNo != e; ++ChunkNo) {
Chris Lattnera29703e2009-09-24 20:39:13 +0000485 size_t MatchLen = 0;
Chris Lattner52870082009-09-24 21:47:32 +0000486 size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion, MatchLen);
Chris Lattnerf15380b2009-09-20 22:35:26 +0000487 if (Pos == StringRef::npos) continue;
488
489 SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
490 CheckPrefix+"-NOT: string occurred!", "error");
Chris Lattner52870082009-09-24 21:47:32 +0000491 SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first,
Chris Lattnerf15380b2009-09-20 22:35:26 +0000492 CheckPrefix+"-NOT: pattern specified here", "note");
493 return 1;
494 }
495
Chris Lattner5dafafd2009-08-15 18:32:21 +0000496
Chris Lattner81115762009-09-21 02:30:42 +0000497 // Otherwise, everything is good. Step over the matched text and remember
498 // the position after the match as the end of the last match.
Chris Lattner9fc66782009-09-24 20:25:55 +0000499 Buffer = Buffer.substr(MatchLen);
Chris Lattner81115762009-09-21 02:30:42 +0000500 LastMatch = Buffer.data();
Chris Lattner81cb8ca2009-07-08 18:44:05 +0000501 }
502
503 return 0;
504}