FileCheck: When a string using variable references fails to match, print
[oota-llvm.git] / utils / FileCheck / FileCheck.cpp
1 //===- 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"
22 #include "llvm/Support/Regex.h"
23 #include "llvm/Support/SourceMgr.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/System/Signals.h"
26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/ADT/StringMap.h"
28 #include <algorithm>
29 using namespace llvm;
30
31 static cl::opt<std::string>
32 CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
33
34 static cl::opt<std::string>
35 InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
36               cl::init("-"), cl::value_desc("filename"));
37
38 static cl::opt<std::string>
39 CheckPrefix("check-prefix", cl::init("CHECK"),
40             cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
41
42 static cl::opt<bool>
43 NoCanonicalizeWhiteSpace("strict-whitespace",
44               cl::desc("Do not treat all horizontal whitespace as equivalent"));
45
46 //===----------------------------------------------------------------------===//
47 // Pattern Handling Code.
48 //===----------------------------------------------------------------------===//
49
50 class Pattern {
51   SMLoc PatternLoc;
52   
53   /// FixedStr - If non-empty, this pattern is a fixed string match with the
54   /// specified fixed string.
55   StringRef FixedStr;
56   
57   /// RegEx - If non-empty, this is a regex pattern.
58   std::string RegExStr;
59   
60   /// VariableUses - Entries in this vector map to uses of a variable in the
61   /// pattern, e.g. "foo[[bar]]baz".  In this case, the RegExStr will contain
62   /// "foobaz" and we'll get an entry in this vector that tells us to insert the
63   /// value of bar at offset 3.
64   std::vector<std::pair<StringRef, unsigned> > VariableUses;
65   
66   /// VariableDefs - Entries in this vector map to definitions of a variable in
67   /// the pattern, e.g. "foo[[bar:.*]]baz".  In this case, the RegExStr will
68   /// contain "foo(.*)baz" and VariableDefs will contain the pair "bar",1.  The
69   /// index indicates what parenthesized value captures the variable value.
70   std::vector<std::pair<StringRef, unsigned> > VariableDefs;
71   
72 public:
73   
74   Pattern() { }
75   
76   bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
77   
78   /// Match - Match the pattern string against the input buffer Buffer.  This
79   /// returns the position that is matched or npos if there is no match.  If
80   /// there is a match, the size of the matched string is returned in MatchLen.
81   ///
82   /// The VariableTable StringMap provides the current values of filecheck
83   /// variables and is updated if this match defines new values.
84   size_t Match(StringRef Buffer, size_t &MatchLen,
85                StringMap<StringRef> &VariableTable) const;
86
87   /// PrintFailureInfo - Print additional information about a failure to match
88   /// involving this pattern.
89   void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
90                         const StringMap<StringRef> &VariableTable) const;
91
92 private:
93   static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr);
94   bool AddRegExToRegEx(StringRef RegExStr, unsigned &CurParen, SourceMgr &SM);
95 };
96
97
98 bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
99   PatternLoc = SMLoc::getFromPointer(PatternStr.data());
100   
101   // Ignore trailing whitespace.
102   while (!PatternStr.empty() &&
103          (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
104     PatternStr = PatternStr.substr(0, PatternStr.size()-1);
105   
106   // Check that there is something on the line.
107   if (PatternStr.empty()) {
108     SM.PrintMessage(PatternLoc, "found empty check string with prefix '" +
109                     CheckPrefix+":'", "error");
110     return true;
111   }
112   
113   // Check to see if this is a fixed string, or if it has regex pieces.
114   if (PatternStr.size() < 2 ||
115       (PatternStr.find("{{") == StringRef::npos &&
116        PatternStr.find("[[") == StringRef::npos)) {
117     FixedStr = PatternStr;
118     return false;
119   }
120   
121   // Paren value #0 is for the fully matched string.  Any new parenthesized
122   // values add from their.
123   unsigned CurParen = 1;
124   
125   // Otherwise, there is at least one regex piece.  Build up the regex pattern
126   // by escaping scary characters in fixed strings, building up one big regex.
127   while (!PatternStr.empty()) {
128     // RegEx matches.
129     if (PatternStr.size() >= 2 &&
130         PatternStr[0] == '{' && PatternStr[1] == '{') {
131      
132       // Otherwise, this is the start of a regex match.  Scan for the }}.
133       size_t End = PatternStr.find("}}");
134       if (End == StringRef::npos) {
135         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
136                         "found start of regex string with no end '}}'", "error");
137         return true;
138       }
139       
140       if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
141         return true;
142       PatternStr = PatternStr.substr(End+2);
143       continue;
144     }
145     
146     // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
147     // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
148     // second form is [[foo]] which is a reference to foo.  The variable name
149     // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
150     // it.  This is to catch some common errors.
151     if (PatternStr.size() >= 2 &&
152         PatternStr[0] == '[' && PatternStr[1] == '[') {
153       // Verify that it is terminated properly.
154       size_t End = PatternStr.find("]]");
155       if (End == StringRef::npos) {
156         SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
157                         "invalid named regex reference, no ]] found", "error");
158         return true;
159       }
160       
161       StringRef MatchStr = PatternStr.substr(2, End-2);
162       PatternStr = PatternStr.substr(End+2);
163       
164       // Get the regex name (e.g. "foo").
165       size_t NameEnd = MatchStr.find(':');
166       StringRef Name = MatchStr.substr(0, NameEnd);
167       
168       if (Name.empty()) {
169         SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
170                         "invalid name in named regex: empty name", "error");
171         return true;
172       }
173
174       // Verify that the name is well formed.
175       for (unsigned i = 0, e = Name.size(); i != e; ++i)
176         if (Name[i] != '_' &&
177             (Name[i] < 'a' || Name[i] > 'z') &&
178             (Name[i] < 'A' || Name[i] > 'Z') &&
179             (Name[i] < '0' || Name[i] > '9')) {
180           SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
181                           "invalid name in named regex", "error");
182           return true;
183         }
184       
185       // Name can't start with a digit.
186       if (isdigit(Name[0])) {
187         SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
188                         "invalid name in named regex", "error");
189         return true;
190       }
191       
192       // Handle [[foo]].
193       if (NameEnd == StringRef::npos) {
194         VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
195         continue;
196       }
197       
198       // Handle [[foo:.*]].
199       VariableDefs.push_back(std::make_pair(Name, CurParen));
200       RegExStr += '(';
201       ++CurParen;
202       
203       if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
204         return true;
205
206       RegExStr += ')';
207     }
208     
209     // Handle fixed string matches.
210     // Find the end, which is the start of the next regex.
211     size_t FixedMatchEnd = PatternStr.find("{{");
212     FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
213     AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr);
214     PatternStr = PatternStr.substr(FixedMatchEnd);
215     continue;
216   }
217
218   return false;
219 }
220
221 void Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) {
222   // Add the characters from FixedStr to the regex, escaping as needed.  This
223   // avoids "leaning toothpicks" in common patterns.
224   for (unsigned i = 0, e = FixedStr.size(); i != e; ++i) {
225     switch (FixedStr[i]) {
226     // These are the special characters matched in "p_ere_exp".
227     case '(':
228     case ')':
229     case '^':
230     case '$':
231     case '|':
232     case '*':
233     case '+':
234     case '?':
235     case '.':
236     case '[':
237     case '\\':
238     case '{':
239       TheStr += '\\';
240       // FALL THROUGH.
241     default:
242       TheStr += FixedStr[i];
243       break;
244     }
245   }
246 }
247
248 bool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen,
249                               SourceMgr &SM) {
250   Regex R(RegexStr);
251   std::string Error;
252   if (!R.isValid(Error)) {
253     SM.PrintMessage(SMLoc::getFromPointer(RegexStr.data()),
254                     "invalid regex: " + Error, "error");
255     return true;
256   }
257   
258   RegExStr += RegexStr.str();
259   CurParen += R.getNumMatches();
260   return false;
261 }
262
263 /// Match - Match the pattern string against the input buffer Buffer.  This
264 /// returns the position that is matched or npos if there is no match.  If
265 /// there is a match, the size of the matched string is returned in MatchLen.
266 size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
267                       StringMap<StringRef> &VariableTable) const {
268   // If this is a fixed string pattern, just match it now.
269   if (!FixedStr.empty()) {
270     MatchLen = FixedStr.size();
271     return Buffer.find(FixedStr);
272   }
273
274   // Regex match.
275   
276   // If there are variable uses, we need to create a temporary string with the
277   // actual value.
278   StringRef RegExToMatch = RegExStr;
279   std::string TmpStr;
280   if (!VariableUses.empty()) {
281     TmpStr = RegExStr;
282     
283     unsigned InsertOffset = 0;
284     for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
285       StringMap<StringRef>::iterator it =
286         VariableTable.find(VariableUses[i].first);
287       // If the variable is undefined, return an error.
288       if (it == VariableTable.end())
289         return StringRef::npos;
290
291       // Look up the value and escape it so that we can plop it into the regex.
292       std::string Value;
293       AddFixedStringToRegEx(it->second, Value);
294       
295       // Plop it into the regex at the adjusted offset.
296       TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
297                     Value.begin(), Value.end());
298       InsertOffset += Value.size();
299     }
300     
301     // Match the newly constructed regex.
302     RegExToMatch = TmpStr;
303   }
304   
305   
306   SmallVector<StringRef, 4> MatchInfo;
307   if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
308     return StringRef::npos;
309   
310   // Successful regex match.
311   assert(!MatchInfo.empty() && "Didn't get any match");
312   StringRef FullMatch = MatchInfo[0];
313   
314   // If this defines any variables, remember their values.
315   for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) {
316     assert(VariableDefs[i].second < MatchInfo.size() &&
317            "Internal paren error");
318     VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second];
319   }
320   
321   MatchLen = FullMatch.size();
322   return FullMatch.data()-Buffer.data();
323 }
324
325 void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
326                                const StringMap<StringRef> &VariableTable) const{
327   // If this is a fixed string, do nothing.
328   if (!FixedStr.empty())
329     return;
330
331   // If this was a regular expression using variables, print the current
332   // variable values.
333   if (!VariableUses.empty()) {
334     for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
335       StringRef Var = VariableUses[i].first;
336       StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
337       SmallString<256> Msg;
338       raw_svector_ostream OS(Msg);
339
340       // Check for undefined variable references.
341       if (it == VariableTable.end()) {
342         OS << "uses undefined variable \"";
343         OS.write_escaped(Var) << "\"";;
344       } else {
345         OS << "with variable \"";
346         OS.write_escaped(Var) << "\" equal to \"";
347         OS.write_escaped(it->second) << "\"";
348       }
349
350       SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), OS.str(), "note",
351                       /*ShowLine=*/false);
352     }
353   }
354 }
355
356 //===----------------------------------------------------------------------===//
357 // Check Strings.
358 //===----------------------------------------------------------------------===//
359
360 /// CheckString - This is a check that we found in the input file.
361 struct CheckString {
362   /// Pat - The pattern to match.
363   Pattern Pat;
364   
365   /// Loc - The location in the match file that the check string was specified.
366   SMLoc Loc;
367   
368   /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
369   /// to a CHECK: directive.
370   bool IsCheckNext;
371   
372   /// NotStrings - These are all of the strings that are disallowed from
373   /// occurring between this match string and the previous one (or start of
374   /// file).
375   std::vector<std::pair<SMLoc, Pattern> > NotStrings;
376   
377   CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
378     : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
379 };
380
381 /// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
382 /// memory buffer, free it, and return a new one.
383 static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
384   SmallVector<char, 16> NewFile;
385   NewFile.reserve(MB->getBufferSize());
386   
387   for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
388        Ptr != End; ++Ptr) {
389     // If C is not a horizontal whitespace, skip it.
390     if (*Ptr != ' ' && *Ptr != '\t') {
391       NewFile.push_back(*Ptr);
392       continue;
393     }
394     
395     // Otherwise, add one space and advance over neighboring space.
396     NewFile.push_back(' ');
397     while (Ptr+1 != End &&
398            (Ptr[1] == ' ' || Ptr[1] == '\t'))
399       ++Ptr;
400   }
401   
402   // Free the old buffer and return a new one.
403   MemoryBuffer *MB2 =
404     MemoryBuffer::getMemBufferCopy(NewFile.data(), 
405                                    NewFile.data() + NewFile.size(),
406                                    MB->getBufferIdentifier());
407   
408   delete MB;
409   return MB2;
410 }
411
412
413 /// ReadCheckFile - Read the check file, which specifies the sequence of
414 /// expected strings.  The strings are added to the CheckStrings vector.
415 static bool ReadCheckFile(SourceMgr &SM,
416                           std::vector<CheckString> &CheckStrings) {
417   // Open the check file, and tell SourceMgr about it.
418   std::string ErrorStr;
419   MemoryBuffer *F =
420     MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
421   if (F == 0) {
422     errs() << "Could not open check file '" << CheckFilename << "': " 
423            << ErrorStr << '\n';
424     return true;
425   }
426   
427   // If we want to canonicalize whitespace, strip excess whitespace from the
428   // buffer containing the CHECK lines.
429   if (!NoCanonicalizeWhiteSpace)
430     F = CanonicalizeInputFile(F);
431   
432   SM.AddNewSourceBuffer(F, SMLoc());
433
434   // Find all instances of CheckPrefix followed by : in the file.
435   StringRef Buffer = F->getBuffer();
436
437   std::vector<std::pair<SMLoc, Pattern> > NotMatches;
438   
439   while (1) {
440     // See if Prefix occurs in the memory buffer.
441     Buffer = Buffer.substr(Buffer.find(CheckPrefix));
442     
443     // If we didn't find a match, we're done.
444     if (Buffer.empty())
445       break;
446     
447     const char *CheckPrefixStart = Buffer.data();
448     
449     // When we find a check prefix, keep track of whether we find CHECK: or
450     // CHECK-NEXT:
451     bool IsCheckNext = false, IsCheckNot = false;
452     
453     // Verify that the : is present after the prefix.
454     if (Buffer[CheckPrefix.size()] == ':') {
455       Buffer = Buffer.substr(CheckPrefix.size()+1);
456     } else if (Buffer.size() > CheckPrefix.size()+6 &&
457                memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
458       Buffer = Buffer.substr(CheckPrefix.size()+7);
459       IsCheckNext = true;
460     } else if (Buffer.size() > CheckPrefix.size()+5 &&
461                memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
462       Buffer = Buffer.substr(CheckPrefix.size()+6);
463       IsCheckNot = true;
464     } else {
465       Buffer = Buffer.substr(1);
466       continue;
467     }
468     
469     // Okay, we found the prefix, yay.  Remember the rest of the line, but
470     // ignore leading and trailing whitespace.
471     Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
472     
473     // Scan ahead to the end of line.
474     size_t EOL = Buffer.find_first_of("\n\r");
475
476     // Parse the pattern.
477     Pattern P;
478     if (P.ParsePattern(Buffer.substr(0, EOL), SM))
479       return true;
480     
481     Buffer = Buffer.substr(EOL);
482
483     
484     // Verify that CHECK-NEXT lines have at least one CHECK line before them.
485     if (IsCheckNext && CheckStrings.empty()) {
486       SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
487                       "found '"+CheckPrefix+"-NEXT:' without previous '"+
488                       CheckPrefix+ ": line", "error");
489       return true;
490     }
491     
492     // Handle CHECK-NOT.
493     if (IsCheckNot) {
494       NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
495                                           P));
496       continue;
497     }
498     
499     
500     // Okay, add the string we captured to the output vector and move on.
501     CheckStrings.push_back(CheckString(P,
502                                        SMLoc::getFromPointer(Buffer.data()),
503                                        IsCheckNext));
504     std::swap(NotMatches, CheckStrings.back().NotStrings);
505   }
506   
507   if (CheckStrings.empty()) {
508     errs() << "error: no check strings found with prefix '" << CheckPrefix
509            << ":'\n";
510     return true;
511   }
512   
513   if (!NotMatches.empty()) {
514     errs() << "error: '" << CheckPrefix
515            << "-NOT:' not supported after last check line.\n";
516     return true;
517   }
518   
519   return false;
520 }
521
522 static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
523                              StringRef Buffer,
524                              StringMap<StringRef> &VariableTable) {
525   // Otherwise, we have an error, emit an error message.
526   SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
527                   "error");
528   
529   // Print the "scanning from here" line.  If the current position is at the
530   // end of a line, advance to the start of the next line.
531   Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
532   
533   SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
534                   "note");
535
536   // Allow the pattern to print additional information if desired.
537   CheckStr.Pat.PrintFailureInfo(SM, Buffer, VariableTable);
538 }
539
540 /// CountNumNewlinesBetween - Count the number of newlines in the specified
541 /// range.
542 static unsigned CountNumNewlinesBetween(StringRef Range) {
543   unsigned NumNewLines = 0;
544   while (1) {
545     // Scan for newline.
546     Range = Range.substr(Range.find_first_of("\n\r"));
547     if (Range.empty()) return NumNewLines;
548     
549     ++NumNewLines;
550     
551     // Handle \n\r and \r\n as a single newline.
552     if (Range.size() > 1 &&
553         (Range[1] == '\n' || Range[1] == '\r') &&
554         (Range[0] != Range[1]))
555       Range = Range.substr(1);
556     Range = Range.substr(1);
557   }
558 }
559
560 int main(int argc, char **argv) {
561   sys::PrintStackTraceOnErrorSignal();
562   PrettyStackTraceProgram X(argc, argv);
563   cl::ParseCommandLineOptions(argc, argv);
564
565   SourceMgr SM;
566   
567   // Read the expected strings from the check file.
568   std::vector<CheckString> CheckStrings;
569   if (ReadCheckFile(SM, CheckStrings))
570     return 2;
571
572   // Open the file to check and add it to SourceMgr.
573   std::string ErrorStr;
574   MemoryBuffer *F =
575     MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
576   if (F == 0) {
577     errs() << "Could not open input file '" << InputFilename << "': " 
578            << ErrorStr << '\n';
579     return true;
580   }
581   
582   // Remove duplicate spaces in the input file if requested.
583   if (!NoCanonicalizeWhiteSpace)
584     F = CanonicalizeInputFile(F);
585   
586   SM.AddNewSourceBuffer(F, SMLoc());
587   
588   /// VariableTable - This holds all the current filecheck variables.
589   StringMap<StringRef> VariableTable;
590   
591   // Check that we have all of the expected strings, in order, in the input
592   // file.
593   StringRef Buffer = F->getBuffer();
594   
595   const char *LastMatch = Buffer.data();
596   
597   for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
598     const CheckString &CheckStr = CheckStrings[StrNo];
599     
600     StringRef SearchFrom = Buffer;
601     
602     // Find StrNo in the file.
603     size_t MatchLen = 0;
604     Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen, VariableTable));
605     
606     // If we didn't find a match, reject the input.
607     if (Buffer.empty()) {
608       PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable);
609       return 1;
610     }
611
612     StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
613
614     // If this check is a "CHECK-NEXT", verify that the previous match was on
615     // the previous line (i.e. that there is one newline between them).
616     if (CheckStr.IsCheckNext) {
617       // Count the number of newlines between the previous match and this one.
618       assert(LastMatch != F->getBufferStart() &&
619              "CHECK-NEXT can't be the first check in a file");
620
621       unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
622       if (NumNewLines == 0) {
623         SM.PrintMessage(CheckStr.Loc,
624                     CheckPrefix+"-NEXT: is on the same line as previous match",
625                         "error");
626         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
627                         "'next' match was here", "note");
628         SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
629                         "previous match was here", "note");
630         return 1;
631       }
632       
633       if (NumNewLines != 1) {
634         SM.PrintMessage(CheckStr.Loc,
635                         CheckPrefix+
636                         "-NEXT: is not on the line after the previous match",
637                         "error");
638         SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
639                         "'next' match was here", "note");
640         SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
641                         "previous match was here", "note");
642         return 1;
643       }
644     }
645     
646     // If this match had "not strings", verify that they don't exist in the
647     // skipped region.
648     for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size();
649          ChunkNo != e; ++ChunkNo) {
650       size_t MatchLen = 0;
651       size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion,
652                                                              MatchLen,
653                                                              VariableTable);
654       if (Pos == StringRef::npos) continue;
655      
656       SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
657                       CheckPrefix+"-NOT: string occurred!", "error");
658       SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first,
659                       CheckPrefix+"-NOT: pattern specified here", "note");
660       return 1;
661     }
662     
663
664     // Otherwise, everything is good.  Step over the matched text and remember
665     // the position after the match as the end of the last match.
666     Buffer = Buffer.substr(MatchLen);
667     LastMatch = Buffer.data();
668   }
669   
670   return 0;
671 }