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 file implements most of the API that will be used by the FileCheck utility 14 // as well as various unittests. 15 //===----------------------------------------------------------------------===// 16 17 #include "llvm/Support/FileCheck.h" 18 #include "llvm/ADT/StringSet.h" 19 #include "llvm/Support/FormatVariadic.h" 20 #include <cstdint> 21 #include <list> 22 #include <map> 23 #include <tuple> 24 #include <utility> 25 26 using namespace llvm; 27 28 /// Parses the given string into the Pattern. 29 /// 30 /// \p Prefix provides which prefix is being matched, \p SM provides the 31 /// SourceMgr used for error reports, and \p LineNumber is the line number in 32 /// the input file from which the pattern string was read. Returns true in 33 /// case of an error, false otherwise. 34 bool FileCheckPattern::ParsePattern(StringRef PatternStr, StringRef Prefix, 35 SourceMgr &SM, unsigned LineNumber, 36 const FileCheckRequest &Req) { 37 bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot; 38 39 this->LineNumber = LineNumber; 40 PatternLoc = SMLoc::getFromPointer(PatternStr.data()); 41 42 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines)) 43 // Ignore trailing whitespace. 44 while (!PatternStr.empty() && 45 (PatternStr.back() == ' ' || PatternStr.back() == '\t')) 46 PatternStr = PatternStr.substr(0, PatternStr.size() - 1); 47 48 // Check that there is something on the line. 49 if (PatternStr.empty() && CheckTy != Check::CheckEmpty) { 50 SM.PrintMessage(PatternLoc, SourceMgr::DK_Error, 51 "found empty check string with prefix '" + Prefix + ":'"); 52 return true; 53 } 54 55 if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) { 56 SM.PrintMessage( 57 PatternLoc, SourceMgr::DK_Error, 58 "found non-empty check string for empty check with prefix '" + Prefix + 59 ":'"); 60 return true; 61 } 62 63 if (CheckTy == Check::CheckEmpty) { 64 RegExStr = "(\n$)"; 65 return false; 66 } 67 68 // Check to see if this is a fixed string, or if it has regex pieces. 69 if (!MatchFullLinesHere && 70 (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && 71 PatternStr.find("[[") == StringRef::npos))) { 72 FixedStr = PatternStr; 73 return false; 74 } 75 76 if (MatchFullLinesHere) { 77 RegExStr += '^'; 78 if (!Req.NoCanonicalizeWhiteSpace) 79 RegExStr += " *"; 80 } 81 82 // Paren value #0 is for the fully matched string. Any new parenthesized 83 // values add from there. 84 unsigned CurParen = 1; 85 86 // Otherwise, there is at least one regex piece. Build up the regex pattern 87 // by escaping scary characters in fixed strings, building up one big regex. 88 while (!PatternStr.empty()) { 89 // RegEx matches. 90 if (PatternStr.startswith("{{")) { 91 // This is the start of a regex match. Scan for the }}. 92 size_t End = PatternStr.find("}}"); 93 if (End == StringRef::npos) { 94 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 95 SourceMgr::DK_Error, 96 "found start of regex string with no end '}}'"); 97 return true; 98 } 99 100 // Enclose {{}} patterns in parens just like [[]] even though we're not 101 // capturing the result for any purpose. This is required in case the 102 // expression contains an alternation like: CHECK: abc{{x|z}}def. We 103 // want this to turn into: "abc(x|z)def" not "abcx|zdef". 104 RegExStr += '('; 105 ++CurParen; 106 107 if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM)) 108 return true; 109 RegExStr += ')'; 110 111 PatternStr = PatternStr.substr(End + 2); 112 continue; 113 } 114 115 // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* 116 // (or some other regex) and assigns it to the FileCheck variable 'foo'. The 117 // second form is [[foo]] which is a reference to foo. The variable name 118 // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject 119 // it. This is to catch some common errors. 120 if (PatternStr.startswith("[[")) { 121 // Find the closing bracket pair ending the match. End is going to be an 122 // offset relative to the beginning of the match string. 123 size_t End = FindRegexVarEnd(PatternStr.substr(2), SM); 124 125 if (End == StringRef::npos) { 126 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 127 SourceMgr::DK_Error, 128 "invalid named regex reference, no ]] found"); 129 return true; 130 } 131 132 StringRef MatchStr = PatternStr.substr(2, End); 133 PatternStr = PatternStr.substr(End + 4); 134 135 // Get the regex name (e.g. "foo"). 136 size_t NameEnd = MatchStr.find(':'); 137 StringRef Name = MatchStr.substr(0, NameEnd); 138 139 if (Name.empty()) { 140 SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 141 "invalid name in named regex: empty name"); 142 return true; 143 } 144 145 // Verify that the name/expression is well formed. FileCheck currently 146 // supports @LINE, @LINE+number, @LINE-number expressions. The check here 147 // is relaxed, more strict check is performed in \c EvaluateExpression. 148 bool IsExpression = false; 149 for (unsigned i = 0, e = Name.size(); i != e; ++i) { 150 if (i == 0) { 151 if (Name[i] == '$') // Global vars start with '$' 152 continue; 153 if (Name[i] == '@') { 154 if (NameEnd != StringRef::npos) { 155 SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 156 SourceMgr::DK_Error, 157 "invalid name in named regex definition"); 158 return true; 159 } 160 IsExpression = true; 161 continue; 162 } 163 } 164 if (Name[i] != '_' && !isalnum(Name[i]) && 165 (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) { 166 SM.PrintMessage(SMLoc::getFromPointer(Name.data() + i), 167 SourceMgr::DK_Error, "invalid name in named regex"); 168 return true; 169 } 170 } 171 172 // Name can't start with a digit. 173 if (isdigit(static_cast<unsigned char>(Name[0]))) { 174 SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 175 "invalid name in named regex"); 176 return true; 177 } 178 179 // Handle [[foo]]. 180 if (NameEnd == StringRef::npos) { 181 // Handle variables that were defined earlier on the same line by 182 // emitting a backreference. 183 if (VariableDefs.find(Name) != VariableDefs.end()) { 184 unsigned VarParenNum = VariableDefs[Name]; 185 if (VarParenNum < 1 || VarParenNum > 9) { 186 SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 187 SourceMgr::DK_Error, 188 "Can't back-reference more than 9 variables"); 189 return true; 190 } 191 AddBackrefToRegEx(VarParenNum); 192 } else { 193 VariableUses.push_back(std::make_pair(Name, RegExStr.size())); 194 } 195 continue; 196 } 197 198 // Handle [[foo:.*]]. 199 VariableDefs[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 RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd)); 214 PatternStr = PatternStr.substr(FixedMatchEnd); 215 } 216 217 if (MatchFullLinesHere) { 218 if (!Req.NoCanonicalizeWhiteSpace) 219 RegExStr += " *"; 220 RegExStr += '$'; 221 } 222 223 return false; 224 } 225 226 bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) { 227 Regex R(RS); 228 std::string Error; 229 if (!R.isValid(Error)) { 230 SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error, 231 "invalid regex: " + Error); 232 return true; 233 } 234 235 RegExStr += RS.str(); 236 CurParen += R.getNumMatches(); 237 return false; 238 } 239 240 void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) { 241 assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number"); 242 std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum); 243 RegExStr += Backref; 244 } 245 246 /// Evaluates expression and stores the result to \p Value. 247 /// 248 /// Returns true on success and false when the expression has invalid syntax. 249 bool FileCheckPattern::EvaluateExpression(StringRef Expr, std::string &Value) const { 250 // The only supported expression is @LINE([\+-]\d+)? 251 if (!Expr.startswith("@LINE")) 252 return false; 253 Expr = Expr.substr(StringRef("@LINE").size()); 254 int Offset = 0; 255 if (!Expr.empty()) { 256 if (Expr[0] == '+') 257 Expr = Expr.substr(1); 258 else if (Expr[0] != '-') 259 return false; 260 if (Expr.getAsInteger(10, Offset)) 261 return false; 262 } 263 Value = llvm::itostr(LineNumber + Offset); 264 return true; 265 } 266 267 /// Matches the pattern string against the input buffer \p Buffer 268 /// 269 /// This returns the position that is matched or npos if there is no match. If 270 /// there is a match, the size of the matched string is returned in \p 271 /// MatchLen. 272 /// 273 /// The \p VariableTable StringMap provides the current values of filecheck 274 /// variables and is updated if this match defines new values. 275 size_t FileCheckPattern::Match(StringRef Buffer, size_t &MatchLen, 276 StringMap<StringRef> &VariableTable) const { 277 // If this is the EOF pattern, match it immediately. 278 if (CheckTy == Check::CheckEOF) { 279 MatchLen = 0; 280 return Buffer.size(); 281 } 282 283 // If this is a fixed string pattern, just match it now. 284 if (!FixedStr.empty()) { 285 MatchLen = FixedStr.size(); 286 return Buffer.find(FixedStr); 287 } 288 289 // Regex match. 290 291 // If there are variable uses, we need to create a temporary string with the 292 // actual value. 293 StringRef RegExToMatch = RegExStr; 294 std::string TmpStr; 295 if (!VariableUses.empty()) { 296 TmpStr = RegExStr; 297 298 unsigned InsertOffset = 0; 299 for (const auto &VariableUse : VariableUses) { 300 std::string Value; 301 302 if (VariableUse.first[0] == '@') { 303 if (!EvaluateExpression(VariableUse.first, Value)) 304 return StringRef::npos; 305 } else { 306 StringMap<StringRef>::iterator it = 307 VariableTable.find(VariableUse.first); 308 // If the variable is undefined, return an error. 309 if (it == VariableTable.end()) 310 return StringRef::npos; 311 312 // Look up the value and escape it so that we can put it into the regex. 313 Value += Regex::escape(it->second); 314 } 315 316 // Plop it into the regex at the adjusted offset. 317 TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset, 318 Value.begin(), Value.end()); 319 InsertOffset += Value.size(); 320 } 321 322 // Match the newly constructed regex. 323 RegExToMatch = TmpStr; 324 } 325 326 SmallVector<StringRef, 4> MatchInfo; 327 if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo)) 328 return StringRef::npos; 329 330 // Successful regex match. 331 assert(!MatchInfo.empty() && "Didn't get any match"); 332 StringRef FullMatch = MatchInfo[0]; 333 334 // If this defines any variables, remember their values. 335 for (const auto &VariableDef : VariableDefs) { 336 assert(VariableDef.second < MatchInfo.size() && "Internal paren error"); 337 VariableTable[VariableDef.first] = MatchInfo[VariableDef.second]; 338 } 339 340 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after 341 // the required preceding newline, which is consumed by the pattern in the 342 // case of CHECK-EMPTY but not CHECK-NEXT. 343 size_t MatchStartSkip = CheckTy == Check::CheckEmpty; 344 MatchLen = FullMatch.size() - MatchStartSkip; 345 return FullMatch.data() - Buffer.data() + MatchStartSkip; 346 } 347 348 349 /// Computes an arbitrary estimate for the quality of matching this pattern at 350 /// the start of \p Buffer; a distance of zero should correspond to a perfect 351 /// match. 352 unsigned 353 FileCheckPattern::ComputeMatchDistance(StringRef Buffer, 354 const StringMap<StringRef> &VariableTable) const { 355 // Just compute the number of matching characters. For regular expressions, we 356 // just compare against the regex itself and hope for the best. 357 // 358 // FIXME: One easy improvement here is have the regex lib generate a single 359 // example regular expression which matches, and use that as the example 360 // string. 361 StringRef ExampleString(FixedStr); 362 if (ExampleString.empty()) 363 ExampleString = RegExStr; 364 365 // Only compare up to the first line in the buffer, or the string size. 366 StringRef BufferPrefix = Buffer.substr(0, ExampleString.size()); 367 BufferPrefix = BufferPrefix.split('\n').first; 368 return BufferPrefix.edit_distance(ExampleString); 369 } 370 371 void FileCheckPattern::PrintVariableUses(const SourceMgr &SM, StringRef Buffer, 372 const StringMap<StringRef> &VariableTable, 373 SMRange MatchRange) const { 374 // If this was a regular expression using variables, print the current 375 // variable values. 376 if (!VariableUses.empty()) { 377 for (const auto &VariableUse : VariableUses) { 378 SmallString<256> Msg; 379 raw_svector_ostream OS(Msg); 380 StringRef Var = VariableUse.first; 381 if (Var[0] == '@') { 382 std::string Value; 383 if (EvaluateExpression(Var, Value)) { 384 OS << "with expression \""; 385 OS.write_escaped(Var) << "\" equal to \""; 386 OS.write_escaped(Value) << "\""; 387 } else { 388 OS << "uses incorrect expression \""; 389 OS.write_escaped(Var) << "\""; 390 } 391 } else { 392 StringMap<StringRef>::const_iterator it = VariableTable.find(Var); 393 394 // Check for undefined variable references. 395 if (it == VariableTable.end()) { 396 OS << "uses undefined variable \""; 397 OS.write_escaped(Var) << "\""; 398 } else { 399 OS << "with variable \""; 400 OS.write_escaped(Var) << "\" equal to \""; 401 OS.write_escaped(it->second) << "\""; 402 } 403 } 404 405 if (MatchRange.isValid()) 406 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(), 407 {MatchRange}); 408 else 409 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), 410 SourceMgr::DK_Note, OS.str()); 411 } 412 } 413 } 414 415 static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy, 416 const SourceMgr &SM, SMLoc Loc, 417 Check::FileCheckType CheckTy, 418 StringRef Buffer, size_t Pos, size_t Len, 419 std::vector<FileCheckDiag> *Diags, 420 bool AdjustPrevDiag = false) { 421 SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos); 422 SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len); 423 SMRange Range(Start, End); 424 if (Diags) { 425 if (AdjustPrevDiag) 426 Diags->rbegin()->MatchTy = MatchTy; 427 else 428 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range); 429 } 430 return Range; 431 } 432 433 void FileCheckPattern::PrintFuzzyMatch( 434 const SourceMgr &SM, StringRef Buffer, 435 const StringMap<StringRef> &VariableTable, 436 std::vector<FileCheckDiag> *Diags) const { 437 // Attempt to find the closest/best fuzzy match. Usually an error happens 438 // because some string in the output didn't exactly match. In these cases, we 439 // would like to show the user a best guess at what "should have" matched, to 440 // save them having to actually check the input manually. 441 size_t NumLinesForward = 0; 442 size_t Best = StringRef::npos; 443 double BestQuality = 0; 444 445 // Use an arbitrary 4k limit on how far we will search. 446 for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { 447 if (Buffer[i] == '\n') 448 ++NumLinesForward; 449 450 // Patterns have leading whitespace stripped, so skip whitespace when 451 // looking for something which looks like a pattern. 452 if (Buffer[i] == ' ' || Buffer[i] == '\t') 453 continue; 454 455 // Compute the "quality" of this match as an arbitrary combination of the 456 // match distance and the number of lines skipped to get to this match. 457 unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); 458 double Quality = Distance + (NumLinesForward / 100.); 459 460 if (Quality < BestQuality || Best == StringRef::npos) { 461 Best = i; 462 BestQuality = Quality; 463 } 464 } 465 466 // Print the "possible intended match here" line if we found something 467 // reasonable and not equal to what we showed in the "scanning from here" 468 // line. 469 if (Best && Best != StringRef::npos && BestQuality < 50) { 470 SMRange MatchRange = 471 ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(), 472 getCheckTy(), Buffer, Best, 0, Diags); 473 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, 474 "possible intended match here"); 475 476 // FIXME: If we wanted to be really friendly we would show why the match 477 // failed, as it can be hard to spot simple one character differences. 478 } 479 } 480 481 /// Finds the closing sequence of a regex variable usage or definition. 482 /// 483 /// \p Str has to point in the beginning of the definition (right after the 484 /// opening sequence). Returns the offset of the closing sequence within Str, 485 /// or npos if it was not found. 486 size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { 487 // Offset keeps track of the current offset within the input Str 488 size_t Offset = 0; 489 // [...] Nesting depth 490 size_t BracketDepth = 0; 491 492 while (!Str.empty()) { 493 if (Str.startswith("]]") && BracketDepth == 0) 494 return Offset; 495 if (Str[0] == '\\') { 496 // Backslash escapes the next char within regexes, so skip them both. 497 Str = Str.substr(2); 498 Offset += 2; 499 } else { 500 switch (Str[0]) { 501 default: 502 break; 503 case '[': 504 BracketDepth++; 505 break; 506 case ']': 507 if (BracketDepth == 0) { 508 SM.PrintMessage(SMLoc::getFromPointer(Str.data()), 509 SourceMgr::DK_Error, 510 "missing closing \"]\" for regex variable"); 511 exit(1); 512 } 513 BracketDepth--; 514 break; 515 } 516 Str = Str.substr(1); 517 Offset++; 518 } 519 } 520 521 return StringRef::npos; 522 } 523 524 /// Canonicalize whitespaces in the file. Line endings are replaced with 525 /// UNIX-style '\n'. 526 StringRef 527 llvm::FileCheck::CanonicalizeFile(MemoryBuffer &MB, 528 SmallVectorImpl<char> &OutputBuffer) { 529 OutputBuffer.reserve(MB.getBufferSize()); 530 531 for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd(); 532 Ptr != End; ++Ptr) { 533 // Eliminate trailing dosish \r. 534 if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { 535 continue; 536 } 537 538 // If current char is not a horizontal whitespace or if horizontal 539 // whitespace canonicalization is disabled, dump it to output as is. 540 if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) { 541 OutputBuffer.push_back(*Ptr); 542 continue; 543 } 544 545 // Otherwise, add one space and advance over neighboring space. 546 OutputBuffer.push_back(' '); 547 while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t')) 548 ++Ptr; 549 } 550 551 // Add a null byte and then return all but that byte. 552 OutputBuffer.push_back('\0'); 553 return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1); 554 } 555 556 FileCheckDiag::FileCheckDiag(const SourceMgr &SM, 557 const Check::FileCheckType &CheckTy, 558 SMLoc CheckLoc, MatchType MatchTy, 559 SMRange InputRange) 560 : CheckTy(CheckTy), MatchTy(MatchTy) { 561 auto Start = SM.getLineAndColumn(InputRange.Start); 562 auto End = SM.getLineAndColumn(InputRange.End); 563 InputStartLine = Start.first; 564 InputStartCol = Start.second; 565 InputEndLine = End.first; 566 InputEndCol = End.second; 567 Start = SM.getLineAndColumn(CheckLoc); 568 CheckLine = Start.first; 569 CheckCol = Start.second; 570 } 571 572 static bool IsPartOfWord(char c) { 573 return (isalnum(c) || c == '-' || c == '_'); 574 } 575 576 Check::FileCheckType &Check::FileCheckType::setCount(int C) { 577 assert(Count > 0 && "zero and negative counts are not supported"); 578 assert((C == 1 || Kind == CheckPlain) && 579 "count supported only for plain CHECK directives"); 580 Count = C; 581 return *this; 582 } 583 584 // Get a description of the type. 585 std::string Check::FileCheckType::getDescription(StringRef Prefix) const { 586 switch (Kind) { 587 case Check::CheckNone: 588 return "invalid"; 589 case Check::CheckPlain: 590 if (Count > 1) 591 return Prefix.str() + "-COUNT"; 592 return Prefix; 593 case Check::CheckNext: 594 return Prefix.str() + "-NEXT"; 595 case Check::CheckSame: 596 return Prefix.str() + "-SAME"; 597 case Check::CheckNot: 598 return Prefix.str() + "-NOT"; 599 case Check::CheckDAG: 600 return Prefix.str() + "-DAG"; 601 case Check::CheckLabel: 602 return Prefix.str() + "-LABEL"; 603 case Check::CheckEmpty: 604 return Prefix.str() + "-EMPTY"; 605 case Check::CheckEOF: 606 return "implicit EOF"; 607 case Check::CheckBadNot: 608 return "bad NOT"; 609 case Check::CheckBadCount: 610 return "bad COUNT"; 611 } 612 llvm_unreachable("unknown FileCheckType"); 613 } 614 615 static std::pair<Check::FileCheckType, StringRef> 616 FindCheckType(StringRef Buffer, StringRef Prefix) { 617 if (Buffer.size() <= Prefix.size()) 618 return {Check::CheckNone, StringRef()}; 619 620 char NextChar = Buffer[Prefix.size()]; 621 622 StringRef Rest = Buffer.drop_front(Prefix.size() + 1); 623 // Verify that the : is present after the prefix. 624 if (NextChar == ':') 625 return {Check::CheckPlain, Rest}; 626 627 if (NextChar != '-') 628 return {Check::CheckNone, StringRef()}; 629 630 if (Rest.consume_front("COUNT-")) { 631 int64_t Count; 632 if (Rest.consumeInteger(10, Count)) 633 // Error happened in parsing integer. 634 return {Check::CheckBadCount, Rest}; 635 if (Count <= 0 || Count > INT32_MAX) 636 return {Check::CheckBadCount, Rest}; 637 if (!Rest.consume_front(":")) 638 return {Check::CheckBadCount, Rest}; 639 return {Check::FileCheckType(Check::CheckPlain).setCount(Count), Rest}; 640 } 641 642 if (Rest.consume_front("NEXT:")) 643 return {Check::CheckNext, Rest}; 644 645 if (Rest.consume_front("SAME:")) 646 return {Check::CheckSame, Rest}; 647 648 if (Rest.consume_front("NOT:")) 649 return {Check::CheckNot, Rest}; 650 651 if (Rest.consume_front("DAG:")) 652 return {Check::CheckDAG, Rest}; 653 654 if (Rest.consume_front("LABEL:")) 655 return {Check::CheckLabel, Rest}; 656 657 if (Rest.consume_front("EMPTY:")) 658 return {Check::CheckEmpty, Rest}; 659 660 // You can't combine -NOT with another suffix. 661 if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") || 662 Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") || 663 Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") || 664 Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:")) 665 return {Check::CheckBadNot, Rest}; 666 667 return {Check::CheckNone, Rest}; 668 } 669 670 // From the given position, find the next character after the word. 671 static size_t SkipWord(StringRef Str, size_t Loc) { 672 while (Loc < Str.size() && IsPartOfWord(Str[Loc])) 673 ++Loc; 674 return Loc; 675 } 676 677 /// Search the buffer for the first prefix in the prefix regular expression. 678 /// 679 /// This searches the buffer using the provided regular expression, however it 680 /// enforces constraints beyond that: 681 /// 1) The found prefix must not be a suffix of something that looks like 682 /// a valid prefix. 683 /// 2) The found prefix must be followed by a valid check type suffix using \c 684 /// FindCheckType above. 685 /// 686 /// Returns a pair of StringRefs into the Buffer, which combines: 687 /// - the first match of the regular expression to satisfy these two is 688 /// returned, 689 /// otherwise an empty StringRef is returned to indicate failure. 690 /// - buffer rewound to the location right after parsed suffix, for parsing 691 /// to continue from 692 /// 693 /// If this routine returns a valid prefix, it will also shrink \p Buffer to 694 /// start at the beginning of the returned prefix, increment \p LineNumber for 695 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of 696 /// check found by examining the suffix. 697 /// 698 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy 699 /// is unspecified. 700 static std::pair<StringRef, StringRef> 701 FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer, 702 unsigned &LineNumber, Check::FileCheckType &CheckTy) { 703 SmallVector<StringRef, 2> Matches; 704 705 while (!Buffer.empty()) { 706 // Find the first (longest) match using the RE. 707 if (!PrefixRE.match(Buffer, &Matches)) 708 // No match at all, bail. 709 return {StringRef(), StringRef()}; 710 711 StringRef Prefix = Matches[0]; 712 Matches.clear(); 713 714 assert(Prefix.data() >= Buffer.data() && 715 Prefix.data() < Buffer.data() + Buffer.size() && 716 "Prefix doesn't start inside of buffer!"); 717 size_t Loc = Prefix.data() - Buffer.data(); 718 StringRef Skipped = Buffer.substr(0, Loc); 719 Buffer = Buffer.drop_front(Loc); 720 LineNumber += Skipped.count('\n'); 721 722 // Check that the matched prefix isn't a suffix of some other check-like 723 // word. 724 // FIXME: This is a very ad-hoc check. it would be better handled in some 725 // other way. Among other things it seems hard to distinguish between 726 // intentional and unintentional uses of this feature. 727 if (Skipped.empty() || !IsPartOfWord(Skipped.back())) { 728 // Now extract the type. 729 StringRef AfterSuffix; 730 std::tie(CheckTy, AfterSuffix) = FindCheckType(Buffer, Prefix); 731 732 // If we've found a valid check type for this prefix, we're done. 733 if (CheckTy != Check::CheckNone) 734 return {Prefix, AfterSuffix}; 735 } 736 737 // If we didn't successfully find a prefix, we need to skip this invalid 738 // prefix and continue scanning. We directly skip the prefix that was 739 // matched and any additional parts of that check-like word. 740 Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size())); 741 } 742 743 // We ran out of buffer while skipping partial matches so give up. 744 return {StringRef(), StringRef()}; 745 } 746 747 /// Read the check file, which specifies the sequence of expected strings. 748 /// 749 /// The strings are added to the CheckStrings vector. Returns true in case of 750 /// an error, false otherwise. 751 bool llvm::FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, 752 Regex &PrefixRE, 753 std::vector<FileCheckString> &CheckStrings) { 754 std::vector<FileCheckPattern> ImplicitNegativeChecks; 755 for (const auto &PatternString : Req.ImplicitCheckNot) { 756 // Create a buffer with fake command line content in order to display the 757 // command line option responsible for the specific implicit CHECK-NOT. 758 std::string Prefix = "-implicit-check-not='"; 759 std::string Suffix = "'"; 760 std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy( 761 Prefix + PatternString + Suffix, "command line"); 762 763 StringRef PatternInBuffer = 764 CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); 765 SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); 766 767 ImplicitNegativeChecks.push_back(FileCheckPattern(Check::CheckNot)); 768 ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, 769 "IMPLICIT-CHECK", SM, 0, Req); 770 } 771 772 std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks; 773 774 // LineNumber keeps track of the line on which CheckPrefix instances are 775 // found. 776 unsigned LineNumber = 1; 777 778 while (1) { 779 Check::FileCheckType CheckTy; 780 781 // See if a prefix occurs in the memory buffer. 782 StringRef UsedPrefix; 783 StringRef AfterSuffix; 784 std::tie(UsedPrefix, AfterSuffix) = 785 FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, CheckTy); 786 if (UsedPrefix.empty()) 787 break; 788 assert(UsedPrefix.data() == Buffer.data() && 789 "Failed to move Buffer's start forward, or pointed prefix outside " 790 "of the buffer!"); 791 assert(AfterSuffix.data() >= Buffer.data() && 792 AfterSuffix.data() < Buffer.data() + Buffer.size() && 793 "Parsing after suffix doesn't start inside of buffer!"); 794 795 // Location to use for error messages. 796 const char *UsedPrefixStart = UsedPrefix.data(); 797 798 // Skip the buffer to the end of parsed suffix (or just prefix, if no good 799 // suffix was processed). 800 Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size()) 801 : AfterSuffix; 802 803 // Complain about useful-looking but unsupported suffixes. 804 if (CheckTy == Check::CheckBadNot) { 805 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error, 806 "unsupported -NOT combo on prefix '" + UsedPrefix + "'"); 807 return true; 808 } 809 810 // Complain about invalid count specification. 811 if (CheckTy == Check::CheckBadCount) { 812 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error, 813 "invalid count in -COUNT specification on prefix '" + 814 UsedPrefix + "'"); 815 return true; 816 } 817 818 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore 819 // leading whitespace. 820 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines)) 821 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); 822 823 // Scan ahead to the end of line. 824 size_t EOL = Buffer.find_first_of("\n\r"); 825 826 // Remember the location of the start of the pattern, for diagnostics. 827 SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); 828 829 // Parse the pattern. 830 FileCheckPattern P(CheckTy); 831 if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber, Req)) 832 return true; 833 834 // Verify that CHECK-LABEL lines do not define or use variables 835 if ((CheckTy == Check::CheckLabel) && P.hasVariable()) { 836 SM.PrintMessage( 837 SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error, 838 "found '" + UsedPrefix + "-LABEL:'" 839 " with variable definition or use"); 840 return true; 841 } 842 843 Buffer = Buffer.substr(EOL); 844 845 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them. 846 if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame || 847 CheckTy == Check::CheckEmpty) && 848 CheckStrings.empty()) { 849 StringRef Type = CheckTy == Check::CheckNext 850 ? "NEXT" 851 : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME"; 852 SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 853 SourceMgr::DK_Error, 854 "found '" + UsedPrefix + "-" + Type + 855 "' without previous '" + UsedPrefix + ": line"); 856 return true; 857 } 858 859 // Handle CHECK-DAG/-NOT. 860 if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) { 861 DagNotMatches.push_back(P); 862 continue; 863 } 864 865 // Okay, add the string we captured to the output vector and move on. 866 CheckStrings.emplace_back(P, UsedPrefix, PatternLoc); 867 std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 868 DagNotMatches = ImplicitNegativeChecks; 869 } 870 871 // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first 872 // prefix as a filler for the error message. 873 if (!DagNotMatches.empty()) { 874 CheckStrings.emplace_back(FileCheckPattern(Check::CheckEOF), *Req.CheckPrefixes.begin(), 875 SMLoc::getFromPointer(Buffer.data())); 876 std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); 877 } 878 879 if (CheckStrings.empty()) { 880 errs() << "error: no check strings found with prefix" 881 << (Req.CheckPrefixes.size() > 1 ? "es " : " "); 882 auto I = Req.CheckPrefixes.begin(); 883 auto E = Req.CheckPrefixes.end(); 884 if (I != E) { 885 errs() << "\'" << *I << ":'"; 886 ++I; 887 } 888 for (; I != E; ++I) 889 errs() << ", \'" << *I << ":'"; 890 891 errs() << '\n'; 892 return true; 893 } 894 895 return false; 896 } 897 898 static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM, 899 StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat, 900 int MatchedCount, StringRef Buffer, 901 StringMap<StringRef> &VariableTable, size_t MatchPos, 902 size_t MatchLen, const FileCheckRequest &Req, 903 std::vector<FileCheckDiag> *Diags) { 904 if (ExpectedMatch) { 905 if (!Req.Verbose) 906 return; 907 if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF) 908 return; 909 } 910 SMRange MatchRange = ProcessMatchResult( 911 ExpectedMatch ? FileCheckDiag::MatchFoundAndExpected 912 : FileCheckDiag::MatchFoundButExcluded, 913 SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags); 914 std::string Message = formatv("{0}: {1} string found in input", 915 Pat.getCheckTy().getDescription(Prefix), 916 (ExpectedMatch ? "expected" : "excluded")) 917 .str(); 918 if (Pat.getCount() > 1) 919 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str(); 920 921 SM.PrintMessage( 922 Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message); 923 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here", 924 {MatchRange}); 925 Pat.PrintVariableUses(SM, Buffer, VariableTable, MatchRange); 926 } 927 928 static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM, 929 const FileCheckString &CheckStr, int MatchedCount, 930 StringRef Buffer, StringMap<StringRef> &VariableTable, 931 size_t MatchPos, size_t MatchLen, FileCheckRequest &Req, 932 std::vector<FileCheckDiag> *Diags) { 933 PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat, 934 MatchedCount, Buffer, VariableTable, MatchPos, MatchLen, Req, 935 Diags); 936 } 937 938 static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM, 939 StringRef Prefix, SMLoc Loc, 940 const FileCheckPattern &Pat, int MatchedCount, 941 StringRef Buffer, StringMap<StringRef> &VariableTable, 942 bool VerboseVerbose, 943 std::vector<FileCheckDiag> *Diags) { 944 if (!ExpectedMatch && !VerboseVerbose) 945 return; 946 947 // Otherwise, we have an error, emit an error message. 948 std::string Message = formatv("{0}: {1} string not found in input", 949 Pat.getCheckTy().getDescription(Prefix), 950 (ExpectedMatch ? "expected" : "excluded")) 951 .str(); 952 if (Pat.getCount() > 1) 953 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str(); 954 955 SM.PrintMessage( 956 Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message); 957 958 // Print the "scanning from here" line. If the current position is at the 959 // end of a line, advance to the start of the next line. 960 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r")); 961 SMRange SearchRange = ProcessMatchResult( 962 ExpectedMatch ? FileCheckDiag::MatchNoneButExpected 963 : FileCheckDiag::MatchNoneAndExcluded, 964 SM, Loc, Pat.getCheckTy(), Buffer, 0, Buffer.size(), Diags); 965 SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here"); 966 967 // Allow the pattern to print additional information if desired. 968 Pat.PrintVariableUses(SM, Buffer, VariableTable); 969 970 if (ExpectedMatch) 971 Pat.PrintFuzzyMatch(SM, Buffer, VariableTable, Diags); 972 } 973 974 static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM, 975 const FileCheckString &CheckStr, int MatchedCount, 976 StringRef Buffer, StringMap<StringRef> &VariableTable, 977 bool VerboseVerbose, 978 std::vector<FileCheckDiag> *Diags) { 979 PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat, 980 MatchedCount, Buffer, VariableTable, VerboseVerbose, Diags); 981 } 982 983 /// Count the number of newlines in the specified range. 984 static unsigned CountNumNewlinesBetween(StringRef Range, 985 const char *&FirstNewLine) { 986 unsigned NumNewLines = 0; 987 while (1) { 988 // Scan for newline. 989 Range = Range.substr(Range.find_first_of("\n\r")); 990 if (Range.empty()) 991 return NumNewLines; 992 993 ++NumNewLines; 994 995 // Handle \n\r and \r\n as a single newline. 996 if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') && 997 (Range[0] != Range[1])) 998 Range = Range.substr(1); 999 Range = Range.substr(1); 1000 1001 if (NumNewLines == 1) 1002 FirstNewLine = Range.begin(); 1003 } 1004 } 1005 1006 /// Match check string and its "not strings" and/or "dag strings". 1007 size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer, 1008 bool IsLabelScanMode, size_t &MatchLen, 1009 StringMap<StringRef> &VariableTable, 1010 FileCheckRequest &Req, 1011 std::vector<FileCheckDiag> *Diags) const { 1012 size_t LastPos = 0; 1013 std::vector<const FileCheckPattern *> NotStrings; 1014 1015 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL 1016 // bounds; we have not processed variable definitions within the bounded block 1017 // yet so cannot handle any final CHECK-DAG yet; this is handled when going 1018 // over the block again (including the last CHECK-LABEL) in normal mode. 1019 if (!IsLabelScanMode) { 1020 // Match "dag strings" (with mixed "not strings" if any). 1021 LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable, Req, Diags); 1022 if (LastPos == StringRef::npos) 1023 return StringRef::npos; 1024 } 1025 1026 // Match itself from the last position after matching CHECK-DAG. 1027 size_t LastMatchEnd = LastPos; 1028 size_t FirstMatchPos = 0; 1029 // Go match the pattern Count times. Majority of patterns only match with 1030 // count 1 though. 1031 assert(Pat.getCount() != 0 && "pattern count can not be zero"); 1032 for (int i = 1; i <= Pat.getCount(); i++) { 1033 StringRef MatchBuffer = Buffer.substr(LastMatchEnd); 1034 size_t CurrentMatchLen; 1035 // get a match at current start point 1036 size_t MatchPos = Pat.Match(MatchBuffer, CurrentMatchLen, VariableTable); 1037 if (i == 1) 1038 FirstMatchPos = LastPos + MatchPos; 1039 1040 // report 1041 if (MatchPos == StringRef::npos) { 1042 PrintNoMatch(true, SM, *this, i, MatchBuffer, VariableTable, 1043 Req.VerboseVerbose, Diags); 1044 return StringRef::npos; 1045 } 1046 PrintMatch(true, SM, *this, i, MatchBuffer, VariableTable, MatchPos, 1047 CurrentMatchLen, Req, Diags); 1048 1049 // move start point after the match 1050 LastMatchEnd += MatchPos + CurrentMatchLen; 1051 } 1052 // Full match len counts from first match pos. 1053 MatchLen = LastMatchEnd - FirstMatchPos; 1054 1055 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT 1056 // or CHECK-NOT 1057 if (!IsLabelScanMode) { 1058 size_t MatchPos = FirstMatchPos - LastPos; 1059 StringRef MatchBuffer = Buffer.substr(LastPos); 1060 StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 1061 1062 // If this check is a "CHECK-NEXT", verify that the previous match was on 1063 // the previous line (i.e. that there is one newline between them). 1064 if (CheckNext(SM, SkippedRegion)) { 1065 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc, 1066 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen, 1067 Diags, Req.Verbose); 1068 return StringRef::npos; 1069 } 1070 1071 // If this check is a "CHECK-SAME", verify that the previous match was on 1072 // the same line (i.e. that there is no newline between them). 1073 if (CheckSame(SM, SkippedRegion)) { 1074 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc, 1075 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen, 1076 Diags, Req.Verbose); 1077 return StringRef::npos; 1078 } 1079 1080 // If this match had "not strings", verify that they don't exist in the 1081 // skipped region. 1082 if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req, Diags)) 1083 return StringRef::npos; 1084 } 1085 1086 return FirstMatchPos; 1087 } 1088 1089 /// Verify there is a single line in the given buffer. 1090 bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { 1091 if (Pat.getCheckTy() != Check::CheckNext && 1092 Pat.getCheckTy() != Check::CheckEmpty) 1093 return false; 1094 1095 Twine CheckName = 1096 Prefix + 1097 Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT"); 1098 1099 // Count the number of newlines between the previous match and this one. 1100 assert(Buffer.data() != 1101 SM.getMemoryBuffer(SM.FindBufferContainingLoc( 1102 SMLoc::getFromPointer(Buffer.data()))) 1103 ->getBufferStart() && 1104 "CHECK-NEXT and CHECK-EMPTY can't be the first check in a file"); 1105 1106 const char *FirstNewLine = nullptr; 1107 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 1108 1109 if (NumNewLines == 0) { 1110 SM.PrintMessage(Loc, SourceMgr::DK_Error, 1111 CheckName + ": is on the same line as previous match"); 1112 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 1113 "'next' match was here"); 1114 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1115 "previous match ended here"); 1116 return true; 1117 } 1118 1119 if (NumNewLines != 1) { 1120 SM.PrintMessage(Loc, SourceMgr::DK_Error, 1121 CheckName + 1122 ": is not on the line after the previous match"); 1123 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 1124 "'next' match was here"); 1125 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1126 "previous match ended here"); 1127 SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, 1128 "non-matching line after previous match is here"); 1129 return true; 1130 } 1131 1132 return false; 1133 } 1134 1135 /// Verify there is no newline in the given buffer. 1136 bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { 1137 if (Pat.getCheckTy() != Check::CheckSame) 1138 return false; 1139 1140 // Count the number of newlines between the previous match and this one. 1141 assert(Buffer.data() != 1142 SM.getMemoryBuffer(SM.FindBufferContainingLoc( 1143 SMLoc::getFromPointer(Buffer.data()))) 1144 ->getBufferStart() && 1145 "CHECK-SAME can't be the first check in a file"); 1146 1147 const char *FirstNewLine = nullptr; 1148 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 1149 1150 if (NumNewLines != 0) { 1151 SM.PrintMessage(Loc, SourceMgr::DK_Error, 1152 Prefix + 1153 "-SAME: is not on the same line as the previous match"); 1154 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 1155 "'next' match was here"); 1156 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 1157 "previous match ended here"); 1158 return true; 1159 } 1160 1161 return false; 1162 } 1163 1164 /// Verify there's no "not strings" in the given buffer. 1165 bool FileCheckString::CheckNot( 1166 const SourceMgr &SM, StringRef Buffer, 1167 const std::vector<const FileCheckPattern *> &NotStrings, 1168 StringMap<StringRef> &VariableTable, const FileCheckRequest &Req, 1169 std::vector<FileCheckDiag> *Diags) const { 1170 for (const FileCheckPattern *Pat : NotStrings) { 1171 assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!"); 1172 1173 size_t MatchLen = 0; 1174 size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable); 1175 1176 if (Pos == StringRef::npos) { 1177 PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, 1178 VariableTable, Req.VerboseVerbose, Diags); 1179 continue; 1180 } 1181 1182 PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, VariableTable, 1183 Pos, MatchLen, Req, Diags); 1184 1185 return true; 1186 } 1187 1188 return false; 1189 } 1190 1191 /// Match "dag strings" and their mixed "not strings". 1192 size_t 1193 FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, 1194 std::vector<const FileCheckPattern *> &NotStrings, 1195 StringMap<StringRef> &VariableTable, 1196 const FileCheckRequest &Req, 1197 std::vector<FileCheckDiag> *Diags) const { 1198 if (DagNotStrings.empty()) 1199 return 0; 1200 1201 // The start of the search range. 1202 size_t StartPos = 0; 1203 1204 struct MatchRange { 1205 size_t Pos; 1206 size_t End; 1207 }; 1208 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match 1209 // ranges are erased from this list once they are no longer in the search 1210 // range. 1211 std::list<MatchRange> MatchRanges; 1212 1213 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG 1214 // group, so we don't use a range-based for loop here. 1215 for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end(); 1216 PatItr != PatEnd; ++PatItr) { 1217 const FileCheckPattern &Pat = *PatItr; 1218 assert((Pat.getCheckTy() == Check::CheckDAG || 1219 Pat.getCheckTy() == Check::CheckNot) && 1220 "Invalid CHECK-DAG or CHECK-NOT!"); 1221 1222 if (Pat.getCheckTy() == Check::CheckNot) { 1223 NotStrings.push_back(&Pat); 1224 continue; 1225 } 1226 1227 assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!"); 1228 1229 // CHECK-DAG always matches from the start. 1230 size_t MatchLen = 0, MatchPos = StartPos; 1231 1232 // Search for a match that doesn't overlap a previous match in this 1233 // CHECK-DAG group. 1234 for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) { 1235 StringRef MatchBuffer = Buffer.substr(MatchPos); 1236 size_t MatchPosBuf = Pat.Match(MatchBuffer, MatchLen, VariableTable); 1237 // With a group of CHECK-DAGs, a single mismatching means the match on 1238 // that group of CHECK-DAGs fails immediately. 1239 if (MatchPosBuf == StringRef::npos) { 1240 PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer, 1241 VariableTable, Req.VerboseVerbose, Diags); 1242 return StringRef::npos; 1243 } 1244 // Re-calc it as the offset relative to the start of the original string. 1245 MatchPos += MatchPosBuf; 1246 if (Req.VerboseVerbose) 1247 PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, 1248 VariableTable, MatchPos, MatchLen, Req, Diags); 1249 MatchRange M{MatchPos, MatchPos + MatchLen}; 1250 if (Req.AllowDeprecatedDagOverlap) { 1251 // We don't need to track all matches in this mode, so we just maintain 1252 // one match range that encompasses the current CHECK-DAG group's 1253 // matches. 1254 if (MatchRanges.empty()) 1255 MatchRanges.insert(MatchRanges.end(), M); 1256 else { 1257 auto Block = MatchRanges.begin(); 1258 Block->Pos = std::min(Block->Pos, M.Pos); 1259 Block->End = std::max(Block->End, M.End); 1260 } 1261 break; 1262 } 1263 // Iterate previous matches until overlapping match or insertion point. 1264 bool Overlap = false; 1265 for (; MI != ME; ++MI) { 1266 if (M.Pos < MI->End) { 1267 // !Overlap => New match has no overlap and is before this old match. 1268 // Overlap => New match overlaps this old match. 1269 Overlap = MI->Pos < M.End; 1270 break; 1271 } 1272 } 1273 if (!Overlap) { 1274 // Insert non-overlapping match into list. 1275 MatchRanges.insert(MI, M); 1276 break; 1277 } 1278 if (Req.VerboseVerbose) { 1279 SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos); 1280 SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End); 1281 SMRange OldRange(OldStart, OldEnd); 1282 SM.PrintMessage(OldStart, SourceMgr::DK_Note, 1283 "match discarded, overlaps earlier DAG match here", 1284 {OldRange}); 1285 if (Diags) 1286 Diags->rbegin()->MatchTy = FileCheckDiag::MatchFoundButDiscarded; 1287 } 1288 MatchPos = MI->End; 1289 } 1290 if (!Req.VerboseVerbose) 1291 PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, VariableTable, 1292 MatchPos, MatchLen, Req, Diags); 1293 1294 // Handle the end of a CHECK-DAG group. 1295 if (std::next(PatItr) == PatEnd || 1296 std::next(PatItr)->getCheckTy() == Check::CheckNot) { 1297 if (!NotStrings.empty()) { 1298 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to 1299 // CHECK-DAG, verify that there are no 'not' strings occurred in that 1300 // region. 1301 StringRef SkippedRegion = 1302 Buffer.slice(StartPos, MatchRanges.begin()->Pos); 1303 if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req, Diags)) 1304 return StringRef::npos; 1305 // Clear "not strings". 1306 NotStrings.clear(); 1307 } 1308 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the 1309 // end of this CHECK-DAG group's match range. 1310 StartPos = MatchRanges.rbegin()->End; 1311 // Don't waste time checking for (impossible) overlaps before that. 1312 MatchRanges.clear(); 1313 } 1314 } 1315 1316 return StartPos; 1317 } 1318 1319 // A check prefix must contain only alphanumeric, hyphens and underscores. 1320 static bool ValidateCheckPrefix(StringRef CheckPrefix) { 1321 Regex Validator("^[a-zA-Z0-9_-]*$"); 1322 return Validator.match(CheckPrefix); 1323 } 1324 1325 bool llvm::FileCheck::ValidateCheckPrefixes() { 1326 StringSet<> PrefixSet; 1327 1328 for (StringRef Prefix : Req.CheckPrefixes) { 1329 // Reject empty prefixes. 1330 if (Prefix == "") 1331 return false; 1332 1333 if (!PrefixSet.insert(Prefix).second) 1334 return false; 1335 1336 if (!ValidateCheckPrefix(Prefix)) 1337 return false; 1338 } 1339 1340 return true; 1341 } 1342 1343 // Combines the check prefixes into a single regex so that we can efficiently 1344 // scan for any of the set. 1345 // 1346 // The semantics are that the longest-match wins which matches our regex 1347 // library. 1348 Regex llvm::FileCheck::buildCheckPrefixRegex() { 1349 // I don't think there's a way to specify an initial value for cl::list, 1350 // so if nothing was specified, add the default 1351 if (Req.CheckPrefixes.empty()) 1352 Req.CheckPrefixes.push_back("CHECK"); 1353 1354 // We already validated the contents of CheckPrefixes so just concatenate 1355 // them as alternatives. 1356 SmallString<32> PrefixRegexStr; 1357 for (StringRef Prefix : Req.CheckPrefixes) { 1358 if (Prefix != Req.CheckPrefixes.front()) 1359 PrefixRegexStr.push_back('|'); 1360 1361 PrefixRegexStr.append(Prefix); 1362 } 1363 1364 return Regex(PrefixRegexStr); 1365 } 1366 1367 // Remove local variables from \p VariableTable. Global variables 1368 // (start with '$') are preserved. 1369 static void ClearLocalVars(StringMap<StringRef> &VariableTable) { 1370 SmallVector<StringRef, 16> LocalVars; 1371 for (const auto &Var : VariableTable) 1372 if (Var.first()[0] != '$') 1373 LocalVars.push_back(Var.first()); 1374 1375 for (const auto &Var : LocalVars) 1376 VariableTable.erase(Var); 1377 } 1378 1379 /// Check the input to FileCheck provided in the \p Buffer against the \p 1380 /// CheckStrings read from the check file. 1381 /// 1382 /// Returns false if the input fails to satisfy the checks. 1383 bool llvm::FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer, 1384 ArrayRef<FileCheckString> CheckStrings, 1385 std::vector<FileCheckDiag> *Diags) { 1386 bool ChecksFailed = false; 1387 1388 /// VariableTable - This holds all the current filecheck variables. 1389 StringMap<StringRef> VariableTable; 1390 1391 for (const auto& Def : Req.GlobalDefines) 1392 VariableTable.insert(StringRef(Def).split('=')); 1393 1394 unsigned i = 0, j = 0, e = CheckStrings.size(); 1395 while (true) { 1396 StringRef CheckRegion; 1397 if (j == e) { 1398 CheckRegion = Buffer; 1399 } else { 1400 const FileCheckString &CheckLabelStr = CheckStrings[j]; 1401 if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { 1402 ++j; 1403 continue; 1404 } 1405 1406 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG 1407 size_t MatchLabelLen = 0; 1408 size_t MatchLabelPos = CheckLabelStr.Check( 1409 SM, Buffer, true, MatchLabelLen, VariableTable, Req, Diags); 1410 if (MatchLabelPos == StringRef::npos) 1411 // Immediately bail of CHECK-LABEL fails, nothing else we can do. 1412 return false; 1413 1414 CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen); 1415 Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen); 1416 ++j; 1417 } 1418 1419 if (Req.EnableVarScope) 1420 ClearLocalVars(VariableTable); 1421 1422 for (; i != j; ++i) { 1423 const FileCheckString &CheckStr = CheckStrings[i]; 1424 1425 // Check each string within the scanned region, including a second check 1426 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) 1427 size_t MatchLen = 0; 1428 size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen, 1429 VariableTable, Req, Diags); 1430 1431 if (MatchPos == StringRef::npos) { 1432 ChecksFailed = true; 1433 i = j; 1434 break; 1435 } 1436 1437 CheckRegion = CheckRegion.substr(MatchPos + MatchLen); 1438 } 1439 1440 if (j == e) 1441 break; 1442 } 1443 1444 // Success if no checks failed. 1445 return !ChecksFailed; 1446 } 1447