+/// ReadCheckFile - Read the check file, which specifies the sequence of
+/// expected strings. The strings are added to the CheckStrings vector.
+static bool ReadCheckFile(SourceMgr &SM,
+ std::vector<CheckString> &CheckStrings) {
+ // Open the check file, and tell SourceMgr about it.
+ OwningPtr<MemoryBuffer> File;
+ if (error_code ec =
+ MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) {
+ errs() << "Could not open check file '" << CheckFilename << "': "
+ << ec.message() << '\n';
+ return true;
+ }
+ MemoryBuffer *F = File.take();
+
+ // If we want to canonicalize whitespace, strip excess whitespace from the
+ // buffer containing the CHECK lines.
+ if (!NoCanonicalizeWhiteSpace)
+ F = CanonicalizeInputFile(F);
+
+ SM.AddNewSourceBuffer(F, SMLoc());
+
+ // Find all instances of CheckPrefix followed by : in the file.
+ StringRef Buffer = F->getBuffer();
+
+ std::vector<std::pair<SMLoc, Pattern> > NotMatches;
+
+ while (1) {
+ // See if Prefix occurs in the memory buffer.
+ Buffer = Buffer.substr(Buffer.find(CheckPrefix));
+
+ // If we didn't find a match, we're done.
+ if (Buffer.empty())
+ break;
+
+ const char *CheckPrefixStart = Buffer.data();
+
+ // When we find a check prefix, keep track of whether we find CHECK: or
+ // CHECK-NEXT:
+ bool IsCheckNext = false, IsCheckNot = false;
+
+ // Verify that the : is present after the prefix.
+ if (Buffer[CheckPrefix.size()] == ':') {
+ Buffer = Buffer.substr(CheckPrefix.size()+1);
+ } else if (Buffer.size() > CheckPrefix.size()+6 &&
+ memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
+ Buffer = Buffer.substr(CheckPrefix.size()+7);
+ IsCheckNext = true;
+ } else if (Buffer.size() > CheckPrefix.size()+5 &&
+ memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
+ Buffer = Buffer.substr(CheckPrefix.size()+6);
+ IsCheckNot = true;
+ } else {
+ Buffer = Buffer.substr(1);
+ continue;
+ }
+
+ // Okay, we found the prefix, yay. Remember the rest of the line, but
+ // ignore leading and trailing whitespace.
+ Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
+
+ // Scan ahead to the end of line.
+ size_t EOL = Buffer.find_first_of("\n\r");
+
+ // Remember the location of the start of the pattern, for diagnostics.
+ SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
+
+ // Parse the pattern.
+ Pattern P;
+ if (P.ParsePattern(Buffer.substr(0, EOL), SM))
+ return true;
+
+ Buffer = Buffer.substr(EOL);
+
+
+ // Verify that CHECK-NEXT lines have at least one CHECK line before them.
+ if (IsCheckNext && CheckStrings.empty()) {
+ SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
+ "found '"+CheckPrefix+"-NEXT:' without previous '"+
+ CheckPrefix+ ": line", "error");
+ return true;
+ }
+
+ // Handle CHECK-NOT.
+ if (IsCheckNot) {
+ NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
+ P));
+ continue;
+ }
+
+
+ // Okay, add the string we captured to the output vector and move on.
+ CheckStrings.push_back(CheckString(P,
+ PatternLoc,
+ IsCheckNext));
+ std::swap(NotMatches, CheckStrings.back().NotStrings);
+ }
+
+ // Add an EOF pattern for any trailing CHECK-NOTs.
+ if (!NotMatches.empty()) {
+ CheckStrings.push_back(CheckString(Pattern(true),
+ SMLoc::getFromPointer(Buffer.data()),
+ false));
+ std::swap(NotMatches, CheckStrings.back().NotStrings);
+ }
+
+ if (CheckStrings.empty()) {
+ errs() << "error: no check strings found with prefix '" << CheckPrefix
+ << ":'\n";
+ return true;
+ }
+
+ return false;
+}
+
+static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
+ StringRef Buffer,
+ StringMap<StringRef> &VariableTable) {
+ // Otherwise, we have an error, emit an error message.
+ SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
+ "error");
+
+ // Print the "scanning from here" line. If the current position is at the
+ // end of a line, advance to the start of the next line.
+ Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
+
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
+ "note");
+
+ // Allow the pattern to print additional information if desired.
+ CheckStr.Pat.PrintFailureInfo(SM, Buffer, VariableTable);
+}
+
+/// CountNumNewlinesBetween - Count the number of newlines in the specified
+/// range.
+static unsigned CountNumNewlinesBetween(StringRef Range) {
+ unsigned NumNewLines = 0;
+ while (1) {
+ // Scan for newline.
+ Range = Range.substr(Range.find_first_of("\n\r"));
+ if (Range.empty()) return NumNewLines;
+
+ ++NumNewLines;
+
+ // Handle \n\r and \r\n as a single newline.
+ if (Range.size() > 1 &&
+ (Range[1] == '\n' || Range[1] == '\r') &&
+ (Range[0] != Range[1]))
+ Range = Range.substr(1);
+ Range = Range.substr(1);
+ }
+}
+