FileCheck.cpp revision adea46ed617982ea07fc3266d52717496c0076ce
181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//                     The LLVM Compiler Infrastructure
481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// This file is distributed under the University of Illinois Open Source
681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// License. See LICENSE.TXT for details.
781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//===----------------------------------------------------------------------===//
981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
1081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// FileCheck does a line-by line check of a file that validates whether it
1181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// contains the expected content.  This is useful for regression tests etc.
1281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
1381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// This program exits with an error status of 2 on error, exit status of 0 if
1481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// the file matched the expected contents, and exit status of 1 if it did not
1581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner// contain the expected contents.
1681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//
1781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner//===----------------------------------------------------------------------===//
1881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
1981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/CommandLine.h"
2081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/MemoryBuffer.h"
2181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/PrettyStackTrace.h"
2281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/SourceMgr.h"
2381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/Support/raw_ostream.h"
2481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner#include "llvm/System/Signals.h"
2581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerusing namespace llvm;
2681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
2781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic cl::opt<std::string>
2881cb8caa3eb482d45e0fd54f8022384256619178Chris LattnerCheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
2981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
3081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic cl::opt<std::string>
3181cb8caa3eb482d45e0fd54f8022384256619178Chris LattnerInputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
3281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner              cl::init("-"), cl::value_desc("filename"));
3381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
3481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic cl::opt<std::string>
3581cb8caa3eb482d45e0fd54f8022384256619178Chris LattnerCheckPrefix("check-prefix", cl::init("CHECK"),
3681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
3781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
3888a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattnerstatic cl::opt<bool>
3988a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris LattnerNoCanonicalizeWhiteSpace("strict-whitespace",
4088a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner              cl::desc("Do not treat all horizontal whitespace as equivalent"));
4188a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner
42a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
43a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner// Pattern Handling Code.
44a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
45a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
469fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattnerclass Pattern {
47207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  /// Str - The string to match.
48adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  StringRef Str;
499fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattnerpublic:
509fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
51a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  Pattern() { }
52a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
53a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
549fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
559fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// Match - Match the pattern string against the input buffer Buffer.  This
569fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// returns the position that is matched or npos if there is no match.  If
579fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// there is a match, the size of the matched string is returned in MatchLen.
589fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  size_t Match(StringRef Buffer, size_t &MatchLen) const {
599fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    MatchLen = Str.size();
609fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    return Buffer.find(Str);
619fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  }
629fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner};
639fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
64a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattnerbool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
65a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  // Ignore trailing whitespace.
66a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  while (!PatternStr.empty() &&
67a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
68a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    PatternStr = PatternStr.substr(0, PatternStr.size()-1);
69a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
70a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  // Check that there is something on the line.
71a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  if (PatternStr.empty()) {
72a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
73a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner                    "found empty check string with prefix '"+CheckPrefix+":'",
74a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner                    "error");
75a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    return true;
76a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  }
77adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
78a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
79a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
80adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  Str = PatternStr;
81a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  return false;
82a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner}
83a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
84a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
85a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
86a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner// Check Strings.
87a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner//===----------------------------------------------------------------------===//
889fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
899fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner/// CheckString - This is a check that we found in the input file.
909fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattnerstruct CheckString {
919fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  /// Pat - The pattern to match.
929fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  Pattern Pat;
93207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner
94207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  /// Loc - The location in the match file that the check string was specified.
95207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  SMLoc Loc;
96207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner
975dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
985dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  /// to a CHECK: directive.
995dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  bool IsCheckNext;
1005dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
101f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  /// NotStrings - These are all of the strings that are disallowed from
102f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  /// occurring between this match string and the previous one (or start of
103f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  /// file).
104a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  std::vector<std::pair<SMLoc, Pattern> > NotStrings;
105f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
1069fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner  CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
1079fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
108207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner};
109207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner
110adea46ed617982ea07fc3266d52717496c0076ceChris Lattner/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
111adea46ed617982ea07fc3266d52717496c0076ceChris Lattner/// memory buffer, free it, and return a new one.
112adea46ed617982ea07fc3266d52717496c0076ceChris Lattnerstatic MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
113adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  SmallVector<char, 16> NewFile;
114adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  NewFile.reserve(MB->getBufferSize());
115adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
116adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
117adea46ed617982ea07fc3266d52717496c0076ceChris Lattner       Ptr != End; ++Ptr) {
118adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    // If C is not a horizontal whitespace, skip it.
119adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    if (*Ptr != ' ' && *Ptr != '\t') {
120adea46ed617982ea07fc3266d52717496c0076ceChris Lattner      NewFile.push_back(*Ptr);
121adea46ed617982ea07fc3266d52717496c0076ceChris Lattner      continue;
122adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    }
123adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
124adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    // Otherwise, add one space and advance over neighboring space.
125adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    NewFile.push_back(' ');
126adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    while (Ptr+1 != End &&
127adea46ed617982ea07fc3266d52717496c0076ceChris Lattner           (Ptr[1] == ' ' || Ptr[1] == '\t'))
128adea46ed617982ea07fc3266d52717496c0076ceChris Lattner      ++Ptr;
129adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  }
130adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
131adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  // Free the old buffer and return a new one.
132adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  MemoryBuffer *MB2 =
133adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    MemoryBuffer::getMemBufferCopy(NewFile.data(),
134adea46ed617982ea07fc3266d52717496c0076ceChris Lattner                                   NewFile.data() + NewFile.size(),
135adea46ed617982ea07fc3266d52717496c0076ceChris Lattner                                   MB->getBufferIdentifier());
136adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
137adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  delete MB;
138adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  return MB2;
139adea46ed617982ea07fc3266d52717496c0076ceChris Lattner}
140adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
14181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
14281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner/// ReadCheckFile - Read the check file, which specifies the sequence of
14381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner/// expected strings.  The strings are added to the CheckStrings vector.
14481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerstatic bool ReadCheckFile(SourceMgr &SM,
145207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner                          std::vector<CheckString> &CheckStrings) {
14681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Open the check file, and tell SourceMgr about it.
14781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  std::string ErrorStr;
14881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  MemoryBuffer *F =
14981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
15081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  if (F == 0) {
15181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    errs() << "Could not open check file '" << CheckFilename << "': "
15281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner           << ErrorStr << '\n';
15381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return true;
15481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
155adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
156adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  // If we want to canonicalize whitespace, strip excess whitespace from the
157adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  // buffer containing the CHECK lines.
158adea46ed617982ea07fc3266d52717496c0076ceChris Lattner  if (!NoCanonicalizeWhiteSpace)
159adea46ed617982ea07fc3266d52717496c0076ceChris Lattner    F = CanonicalizeInputFile(F);
160adea46ed617982ea07fc3266d52717496c0076ceChris Lattner
16181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  SM.AddNewSourceBuffer(F, SMLoc());
16281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
163d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner  // Find all instances of CheckPrefix followed by : in the file.
16496077036f06478d96c123283a50cfba49858fd40Chris Lattner  StringRef Buffer = F->getBuffer();
16581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
166a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner  std::vector<std::pair<SMLoc, Pattern> > NotMatches;
167f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
16881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  while (1) {
16981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // See if Prefix occurs in the memory buffer.
17096077036f06478d96c123283a50cfba49858fd40Chris Lattner    Buffer = Buffer.substr(Buffer.find(CheckPrefix));
17181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
17281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // If we didn't find a match, we're done.
17396077036f06478d96c123283a50cfba49858fd40Chris Lattner    if (Buffer.empty())
17481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner      break;
17581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
17696077036f06478d96c123283a50cfba49858fd40Chris Lattner    const char *CheckPrefixStart = Buffer.data();
1775dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
1785dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // When we find a check prefix, keep track of whether we find CHECK: or
1795dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // CHECK-NEXT:
180f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    bool IsCheckNext = false, IsCheckNot = false;
1815dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
182d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner    // Verify that the : is present after the prefix.
18396077036f06478d96c123283a50cfba49858fd40Chris Lattner    if (Buffer[CheckPrefix.size()] == ':') {
18496077036f06478d96c123283a50cfba49858fd40Chris Lattner      Buffer = Buffer.substr(CheckPrefix.size()+1);
18596077036f06478d96c123283a50cfba49858fd40Chris Lattner    } else if (Buffer.size() > CheckPrefix.size()+6 &&
18696077036f06478d96c123283a50cfba49858fd40Chris Lattner               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
18796077036f06478d96c123283a50cfba49858fd40Chris Lattner      Buffer = Buffer.substr(CheckPrefix.size()+7);
1885dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      IsCheckNext = true;
189f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    } else if (Buffer.size() > CheckPrefix.size()+5 &&
190f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
191f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      Buffer = Buffer.substr(CheckPrefix.size()+6);
192f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      IsCheckNot = true;
1935dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    } else {
19496077036f06478d96c123283a50cfba49858fd40Chris Lattner      Buffer = Buffer.substr(1);
195d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner      continue;
196d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner    }
197d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner
19881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Okay, we found the prefix, yay.  Remember the rest of the line, but
19981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // ignore leading and trailing whitespace.
200f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
20181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
20281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Scan ahead to the end of line.
20396077036f06478d96c123283a50cfba49858fd40Chris Lattner    size_t EOL = Buffer.find_first_of("\n\r");
204a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
205a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    // Parse the pattern.
206a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    Pattern P;
207a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    if (P.ParsePattern(Buffer.substr(0, EOL), SM))
20881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner      return true;
20981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
210a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    Buffer = Buffer.substr(EOL);
211a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
212f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
2135dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
2145dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    if (IsCheckNext && CheckStrings.empty()) {
2155dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
2165dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
2175dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                      CheckPrefix+ ": line", "error");
2185dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      return true;
2195dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    }
2205dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
221a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    // Handle CHECK-NOT.
222a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    if (IsCheckNot) {
223a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
224a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner                                          P));
225a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner      continue;
226a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner    }
227a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner
2289fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner
22981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Okay, add the string we captured to the output vector and move on.
2309fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    CheckStrings.push_back(CheckString(P,
23196077036f06478d96c123283a50cfba49858fd40Chris Lattner                                       SMLoc::getFromPointer(Buffer.data()),
2325dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                                       IsCheckNext));
233f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    std::swap(NotMatches, CheckStrings.back().NotStrings);
23481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
23581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
23681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  if (CheckStrings.empty()) {
237d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner    errs() << "error: no check strings found with prefix '" << CheckPrefix
238d7e250527c38297c900db43a9e2f1e56b235b3ccChris Lattner           << ":'\n";
23981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return true;
24081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
24181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
242f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  if (!NotMatches.empty()) {
243f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    errs() << "error: '" << CheckPrefix
244f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner           << "-NOT:' not supported after last check line.\n";
245f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    return true;
246f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  }
247f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
24881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  return false;
24981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner}
25081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
2515dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattnerstatic void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
25296077036f06478d96c123283a50cfba49858fd40Chris Lattner                             StringRef Buffer) {
2535dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  // Otherwise, we have an error, emit an error message.
2545dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
2555dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                  "error");
2565dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
2575dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  // Print the "scanning from here" line.  If the current position is at the
2585dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  // end of a line, advance to the start of the next line.
25996077036f06478d96c123283a50cfba49858fd40Chris Lattner  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
2605dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
26196077036f06478d96c123283a50cfba49858fd40Chris Lattner  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
2625dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                  "note");
2635dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner}
2645dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
2653711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner/// CountNumNewlinesBetween - Count the number of newlines in the specified
2663711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner/// range.
2673711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattnerstatic unsigned CountNumNewlinesBetween(StringRef Range) {
2685dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  unsigned NumNewLines = 0;
2693711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner  while (1) {
2705dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // Scan for newline.
2713711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    Range = Range.substr(Range.find_first_of("\n\r"));
2723711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    if (Range.empty()) return NumNewLines;
2735dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
2745dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    ++NumNewLines;
2755dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
2765dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // Handle \n\r and \r\n as a single newline.
2773711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    if (Range.size() > 1 &&
2783711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner        (Range[1] == '\n' || Range[1] == '\r') &&
2793711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner        (Range[0] != Range[1]))
2803711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner      Range = Range.substr(1);
2813711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    Range = Range.substr(1);
2825dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner  }
2835dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner}
2845dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
28581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattnerint main(int argc, char **argv) {
28681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  sys::PrintStackTraceOnErrorSignal();
28781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  PrettyStackTraceProgram X(argc, argv);
28881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  cl::ParseCommandLineOptions(argc, argv);
28981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
29081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  SourceMgr SM;
29181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
29281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Read the expected strings from the check file.
293207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner  std::vector<CheckString> CheckStrings;
29481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  if (ReadCheckFile(SM, CheckStrings))
29581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return 2;
29681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
29781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Open the file to check and add it to SourceMgr.
29881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  std::string ErrorStr;
29981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  MemoryBuffer *F =
30081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
30181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  if (F == 0) {
30281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    errs() << "Could not open input file '" << InputFilename << "': "
30381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner           << ErrorStr << '\n';
30481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    return true;
30581cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
30688a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner
30788a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner  // Remove duplicate spaces in the input file if requested.
30888a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner  if (!NoCanonicalizeWhiteSpace)
30988a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner    F = CanonicalizeInputFile(F);
31088a7e9ee8dd2f1d2f40cdb9c378f050e45161783Chris Lattner
31181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  SM.AddNewSourceBuffer(F, SMLoc());
31281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
31381cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // Check that we have all of the expected strings, in order, in the input
31481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  // file.
31596077036f06478d96c123283a50cfba49858fd40Chris Lattner  StringRef Buffer = F->getBuffer();
31681cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
317f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner  const char *LastMatch = Buffer.data();
318f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
31981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
320207e1bcf897d1c732f717b9773029651ecc59ab2Chris Lattner    const CheckString &CheckStr = CheckStrings[StrNo];
32181cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
32296077036f06478d96c123283a50cfba49858fd40Chris Lattner    StringRef SearchFrom = Buffer;
32396077036f06478d96c123283a50cfba49858fd40Chris Lattner
32481cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    // Find StrNo in the file.
3259fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    size_t MatchLen = 0;
3269fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));
32781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
3285dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // If we didn't find a match, reject the input.
32996077036f06478d96c123283a50cfba49858fd40Chris Lattner    if (Buffer.empty()) {
33096077036f06478d96c123283a50cfba49858fd40Chris Lattner      PrintCheckFailed(SM, CheckStr, SearchFrom);
3315dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      return 1;
33281cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner    }
3333711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner
3343711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
3353711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner
3365dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // If this check is a "CHECK-NEXT", verify that the previous match was on
3375dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    // the previous line (i.e. that there is one newline between them).
3385dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    if (CheckStr.IsCheckNext) {
3395dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      // Count the number of newlines between the previous match and this one.
340f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      assert(LastMatch != F->getBufferStart() &&
341f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner             "CHECK-NEXT can't be the first check in a file");
3425dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
3433711b7adccc766fdbafbc6b22c2bb6c45181a3b9Chris Lattner      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
3445dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      if (NumNewLines == 0) {
3450b2353f277f7a92b48af20f9804c6c35d96ecb75Chris Lattner        SM.PrintMessage(CheckStr.Loc,
3465dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                    CheckPrefix+"-NEXT: is on the same line as previous match",
3475dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                        "error");
34896077036f06478d96c123283a50cfba49858fd40Chris Lattner        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
3490b2353f277f7a92b48af20f9804c6c35d96ecb75Chris Lattner                        "'next' match was here", "note");
3505dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
3515dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                        "previous match was here", "note");
3525dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner        return 1;
3535dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      }
3545dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
3555dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      if (NumNewLines != 1) {
3560b2353f277f7a92b48af20f9804c6c35d96ecb75Chris Lattner        SM.PrintMessage(CheckStr.Loc,
3575dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                        CheckPrefix+
3585dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                        "-NEXT: is not on the line after the previous match",
3595dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                        "error");
36096077036f06478d96c123283a50cfba49858fd40Chris Lattner        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
3610b2353f277f7a92b48af20f9804c6c35d96ecb75Chris Lattner                        "'next' match was here", "note");
3625dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
3635dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner                        "previous match was here", "note");
3645dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner        return 1;
3655dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner      }
3665dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner    }
367f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
368f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    // If this match had "not strings", verify that they don't exist in the
369f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    // skipped region.
370f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    for (unsigned i = 0, e = CheckStr.NotStrings.size(); i != e; ++i) {
371a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner      size_t MatchLen = 0;
372a29703e8426763fa5232f9a91e6a5fce4d4244d6Chris Lattner      size_t Pos = CheckStr.NotStrings[i].second.Match(SkippedRegion, MatchLen);
373f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      if (Pos == StringRef::npos) continue;
374f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
375f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
376f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner                      CheckPrefix+"-NOT: string occurred!", "error");
377f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      SM.PrintMessage(CheckStr.NotStrings[i].first,
378f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner                      CheckPrefix+"-NOT: pattern specified here", "note");
379f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner      return 1;
380f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner    }
381f15380ba8ae35941dcd56d9a288ad023295dde30Chris Lattner
3825dafafdeb4d89b37c6b7efbeabaa7d818c7023feChris Lattner
38381115765218f1c1505ab6faf843ee4baf292d45fChris Lattner    // Otherwise, everything is good.  Step over the matched text and remember
38481115765218f1c1505ab6faf843ee4baf292d45fChris Lattner    // the position after the match as the end of the last match.
3859fc6678bea11f32acba4e9b6624ae9a0d3a9287bChris Lattner    Buffer = Buffer.substr(MatchLen);
38681115765218f1c1505ab6faf843ee4baf292d45fChris Lattner    LastMatch = Buffer.data();
38781cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  }
38881cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner
38981cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner  return 0;
39081cb8caa3eb482d45e0fd54f8022384256619178Chris Lattner}
391