Recommit r373598 "[yaml2obj/obj2yaml] - Add support for SHT_LLVM_ADDRSIG sections."
[llvm-complete.git] / lib / Support / FileCheck.cpp
blobc3f537b35243ec303165e5c9827f65215020d153
1 //===- FileCheck.cpp - Check that File's Contents match what is expected --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // FileCheck does a line-by line check of a file that validates whether it
10 // contains the expected content. This is useful for regression tests etc.
12 // This file implements most of the API that will be used by the FileCheck utility
13 // as well as various unittests.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Support/FileCheck.h"
17 #include "FileCheckImpl.h"
18 #include "llvm/ADT/StringSet.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Support/FormatVariadic.h"
21 #include <cstdint>
22 #include <list>
23 #include <tuple>
24 #include <utility>
26 using namespace llvm;
28 Expected<uint64_t> FileCheckNumericVariableUse::eval() const {
29 Optional<uint64_t> Value = NumericVariable->getValue();
30 if (Value)
31 return *Value;
33 return make_error<FileCheckUndefVarError>(Name);
36 Expected<uint64_t> FileCheckASTBinop::eval() const {
37 Expected<uint64_t> LeftOp = LeftOperand->eval();
38 Expected<uint64_t> RightOp = RightOperand->eval();
40 // Bubble up any error (e.g. undefined variables) in the recursive
41 // evaluation.
42 if (!LeftOp || !RightOp) {
43 Error Err = Error::success();
44 if (!LeftOp)
45 Err = joinErrors(std::move(Err), LeftOp.takeError());
46 if (!RightOp)
47 Err = joinErrors(std::move(Err), RightOp.takeError());
48 return std::move(Err);
51 return EvalBinop(*LeftOp, *RightOp);
54 Expected<std::string> FileCheckNumericSubstitution::getResult() const {
55 Expected<uint64_t> EvaluatedValue = ExpressionAST->eval();
56 if (!EvaluatedValue)
57 return EvaluatedValue.takeError();
58 return utostr(*EvaluatedValue);
61 Expected<std::string> FileCheckStringSubstitution::getResult() const {
62 // Look up the value and escape it so that we can put it into the regex.
63 Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
64 if (!VarVal)
65 return VarVal.takeError();
66 return Regex::escape(*VarVal);
69 bool FileCheckPattern::isValidVarNameStart(char C) {
70 return C == '_' || isalpha(C);
73 Expected<FileCheckPattern::VariableProperties>
74 FileCheckPattern::parseVariable(StringRef &Str, const SourceMgr &SM) {
75 if (Str.empty())
76 return FileCheckErrorDiagnostic::get(SM, Str, "empty variable name");
78 bool ParsedOneChar = false;
79 unsigned I = 0;
80 bool IsPseudo = Str[0] == '@';
82 // Global vars start with '$'.
83 if (Str[0] == '$' || IsPseudo)
84 ++I;
86 for (unsigned E = Str.size(); I != E; ++I) {
87 if (!ParsedOneChar && !isValidVarNameStart(Str[I]))
88 return FileCheckErrorDiagnostic::get(SM, Str, "invalid variable name");
90 // Variable names are composed of alphanumeric characters and underscores.
91 if (Str[I] != '_' && !isalnum(Str[I]))
92 break;
93 ParsedOneChar = true;
96 StringRef Name = Str.take_front(I);
97 Str = Str.substr(I);
98 return VariableProperties {Name, IsPseudo};
101 // StringRef holding all characters considered as horizontal whitespaces by
102 // FileCheck input canonicalization.
103 constexpr StringLiteral SpaceChars = " \t";
105 // Parsing helper function that strips the first character in S and returns it.
106 static char popFront(StringRef &S) {
107 char C = S.front();
108 S = S.drop_front();
109 return C;
112 char FileCheckUndefVarError::ID = 0;
113 char FileCheckErrorDiagnostic::ID = 0;
114 char FileCheckNotFoundError::ID = 0;
116 Expected<FileCheckNumericVariable *>
117 FileCheckPattern::parseNumericVariableDefinition(
118 StringRef &Expr, FileCheckPatternContext *Context,
119 Optional<size_t> LineNumber, const SourceMgr &SM) {
120 Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM);
121 if (!ParseVarResult)
122 return ParseVarResult.takeError();
123 StringRef Name = ParseVarResult->Name;
125 if (ParseVarResult->IsPseudo)
126 return FileCheckErrorDiagnostic::get(
127 SM, Name, "definition of pseudo numeric variable unsupported");
129 // Detect collisions between string and numeric variables when the latter
130 // is created later than the former.
131 if (Context->DefinedVariableTable.find(Name) !=
132 Context->DefinedVariableTable.end())
133 return FileCheckErrorDiagnostic::get(
134 SM, Name, "string variable with name '" + Name + "' already exists");
136 Expr = Expr.ltrim(SpaceChars);
137 if (!Expr.empty())
138 return FileCheckErrorDiagnostic::get(
139 SM, Expr, "unexpected characters after numeric variable name");
141 FileCheckNumericVariable *DefinedNumericVariable;
142 auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
143 if (VarTableIter != Context->GlobalNumericVariableTable.end())
144 DefinedNumericVariable = VarTableIter->second;
145 else
146 DefinedNumericVariable = Context->makeNumericVariable(Name, LineNumber);
148 return DefinedNumericVariable;
151 Expected<std::unique_ptr<FileCheckNumericVariableUse>>
152 FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,
153 Optional<size_t> LineNumber,
154 FileCheckPatternContext *Context,
155 const SourceMgr &SM) {
156 if (IsPseudo && !Name.equals("@LINE"))
157 return FileCheckErrorDiagnostic::get(
158 SM, Name, "invalid pseudo numeric variable '" + Name + "'");
160 // Numeric variable definitions and uses are parsed in the order in which
161 // they appear in the CHECK patterns. For each definition, the pointer to the
162 // class instance of the corresponding numeric variable definition is stored
163 // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
164 // we get below is null, it means no such variable was defined before. When
165 // that happens, we create a dummy variable so that parsing can continue. All
166 // uses of undefined variables, whether string or numeric, are then diagnosed
167 // in printSubstitutions() after failing to match.
168 auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
169 FileCheckNumericVariable *NumericVariable;
170 if (VarTableIter != Context->GlobalNumericVariableTable.end())
171 NumericVariable = VarTableIter->second;
172 else {
173 NumericVariable = Context->makeNumericVariable(Name);
174 Context->GlobalNumericVariableTable[Name] = NumericVariable;
177 Optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();
178 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
179 return FileCheckErrorDiagnostic::get(
180 SM, Name,
181 "numeric variable '" + Name +
182 "' defined earlier in the same CHECK directive");
184 return std::make_unique<FileCheckNumericVariableUse>(Name, NumericVariable);
187 Expected<std::unique_ptr<FileCheckExpressionAST>>
188 FileCheckPattern::parseNumericOperand(StringRef &Expr, AllowedOperand AO,
189 Optional<size_t> LineNumber,
190 FileCheckPatternContext *Context,
191 const SourceMgr &SM) {
192 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
193 // Try to parse as a numeric variable use.
194 Expected<FileCheckPattern::VariableProperties> ParseVarResult =
195 parseVariable(Expr, SM);
196 if (ParseVarResult)
197 return parseNumericVariableUse(ParseVarResult->Name,
198 ParseVarResult->IsPseudo, LineNumber,
199 Context, SM);
200 if (AO == AllowedOperand::LineVar)
201 return ParseVarResult.takeError();
202 // Ignore the error and retry parsing as a literal.
203 consumeError(ParseVarResult.takeError());
206 // Otherwise, parse it as a literal.
207 uint64_t LiteralValue;
208 if (!Expr.consumeInteger(/*Radix=*/10, LiteralValue))
209 return std::make_unique<FileCheckExpressionLiteral>(LiteralValue);
211 return FileCheckErrorDiagnostic::get(SM, Expr,
212 "invalid operand format '" + Expr + "'");
215 static uint64_t add(uint64_t LeftOp, uint64_t RightOp) {
216 return LeftOp + RightOp;
219 static uint64_t sub(uint64_t LeftOp, uint64_t RightOp) {
220 return LeftOp - RightOp;
223 Expected<std::unique_ptr<FileCheckExpressionAST>> FileCheckPattern::parseBinop(
224 StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
225 bool IsLegacyLineExpr, Optional<size_t> LineNumber,
226 FileCheckPatternContext *Context, const SourceMgr &SM) {
227 Expr = Expr.ltrim(SpaceChars);
228 if (Expr.empty())
229 return std::move(LeftOp);
231 // Check if this is a supported operation and select a function to perform
232 // it.
233 SMLoc OpLoc = SMLoc::getFromPointer(Expr.data());
234 char Operator = popFront(Expr);
235 binop_eval_t EvalBinop;
236 switch (Operator) {
237 case '+':
238 EvalBinop = add;
239 break;
240 case '-':
241 EvalBinop = sub;
242 break;
243 default:
244 return FileCheckErrorDiagnostic::get(
245 SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");
248 // Parse right operand.
249 Expr = Expr.ltrim(SpaceChars);
250 if (Expr.empty())
251 return FileCheckErrorDiagnostic::get(SM, Expr,
252 "missing operand in expression");
253 // The second operand in a legacy @LINE expression is always a literal.
254 AllowedOperand AO =
255 IsLegacyLineExpr ? AllowedOperand::Literal : AllowedOperand::Any;
256 Expected<std::unique_ptr<FileCheckExpressionAST>> RightOpResult =
257 parseNumericOperand(Expr, AO, LineNumber, Context, SM);
258 if (!RightOpResult)
259 return RightOpResult;
261 Expr = Expr.ltrim(SpaceChars);
262 return std::make_unique<FileCheckASTBinop>(EvalBinop, std::move(LeftOp),
263 std::move(*RightOpResult));
266 Expected<std::unique_ptr<FileCheckExpressionAST>>
267 FileCheckPattern::parseNumericSubstitutionBlock(
268 StringRef Expr,
269 Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
270 bool IsLegacyLineExpr, Optional<size_t> LineNumber,
271 FileCheckPatternContext *Context, const SourceMgr &SM) {
272 std::unique_ptr<FileCheckExpressionAST> ExpressionAST = nullptr;
273 StringRef DefExpr = StringRef();
274 DefinedNumericVariable = None;
275 // Save variable definition expression if any.
276 size_t DefEnd = Expr.find(':');
277 if (DefEnd != StringRef::npos) {
278 DefExpr = Expr.substr(0, DefEnd);
279 Expr = Expr.substr(DefEnd + 1);
282 // Parse the expression itself.
283 Expr = Expr.ltrim(SpaceChars);
284 if (!Expr.empty()) {
285 // The first operand in a legacy @LINE expression is always the @LINE
286 // pseudo variable.
287 AllowedOperand AO =
288 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
289 Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
290 parseNumericOperand(Expr, AO, LineNumber, Context, SM);
291 while (ParseResult && !Expr.empty()) {
292 ParseResult = parseBinop(Expr, std::move(*ParseResult), IsLegacyLineExpr,
293 LineNumber, Context, SM);
294 // Legacy @LINE expressions only allow 2 operands.
295 if (ParseResult && IsLegacyLineExpr && !Expr.empty())
296 return FileCheckErrorDiagnostic::get(
297 SM, Expr,
298 "unexpected characters at end of expression '" + Expr + "'");
300 if (!ParseResult)
301 return ParseResult;
302 ExpressionAST = std::move(*ParseResult);
305 // Parse the numeric variable definition.
306 if (DefEnd != StringRef::npos) {
307 DefExpr = DefExpr.ltrim(SpaceChars);
308 Expected<FileCheckNumericVariable *> ParseResult =
309 parseNumericVariableDefinition(DefExpr, Context, LineNumber, SM);
311 if (!ParseResult)
312 return ParseResult.takeError();
313 DefinedNumericVariable = *ParseResult;
316 return std::move(ExpressionAST);
319 bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
320 SourceMgr &SM,
321 const FileCheckRequest &Req) {
322 bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
324 PatternLoc = SMLoc::getFromPointer(PatternStr.data());
326 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
327 // Ignore trailing whitespace.
328 while (!PatternStr.empty() &&
329 (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
330 PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
332 // Check that there is something on the line.
333 if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
334 SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
335 "found empty check string with prefix '" + Prefix + ":'");
336 return true;
339 if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
340 SM.PrintMessage(
341 PatternLoc, SourceMgr::DK_Error,
342 "found non-empty check string for empty check with prefix '" + Prefix +
343 ":'");
344 return true;
347 if (CheckTy == Check::CheckEmpty) {
348 RegExStr = "(\n$)";
349 return false;
352 // Check to see if this is a fixed string, or if it has regex pieces.
353 if (!MatchFullLinesHere &&
354 (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
355 PatternStr.find("[[") == StringRef::npos))) {
356 FixedStr = PatternStr;
357 return false;
360 if (MatchFullLinesHere) {
361 RegExStr += '^';
362 if (!Req.NoCanonicalizeWhiteSpace)
363 RegExStr += " *";
366 // Paren value #0 is for the fully matched string. Any new parenthesized
367 // values add from there.
368 unsigned CurParen = 1;
370 // Otherwise, there is at least one regex piece. Build up the regex pattern
371 // by escaping scary characters in fixed strings, building up one big regex.
372 while (!PatternStr.empty()) {
373 // RegEx matches.
374 if (PatternStr.startswith("{{")) {
375 // This is the start of a regex match. Scan for the }}.
376 size_t End = PatternStr.find("}}");
377 if (End == StringRef::npos) {
378 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
379 SourceMgr::DK_Error,
380 "found start of regex string with no end '}}'");
381 return true;
384 // Enclose {{}} patterns in parens just like [[]] even though we're not
385 // capturing the result for any purpose. This is required in case the
386 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
387 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
388 RegExStr += '(';
389 ++CurParen;
391 if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
392 return true;
393 RegExStr += ')';
395 PatternStr = PatternStr.substr(End + 2);
396 continue;
399 // String and numeric substitution blocks. Pattern substitution blocks come
400 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
401 // other regex) and assigns it to the string variable 'foo'. The latter
402 // substitutes foo's value. Numeric substitution blocks recognize the same
403 // form as string ones, but start with a '#' sign after the double
404 // brackets. They also accept a combined form which sets a numeric variable
405 // to the evaluation of an expression. Both string and numeric variable
406 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
407 // valid, as this helps catch some common errors.
408 if (PatternStr.startswith("[[")) {
409 StringRef UnparsedPatternStr = PatternStr.substr(2);
410 // Find the closing bracket pair ending the match. End is going to be an
411 // offset relative to the beginning of the match string.
412 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
413 StringRef MatchStr = UnparsedPatternStr.substr(0, End);
414 bool IsNumBlock = MatchStr.consume_front("#");
416 if (End == StringRef::npos) {
417 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
418 SourceMgr::DK_Error,
419 "Invalid substitution block, no ]] found");
420 return true;
422 // Strip the substitution block we are parsing. End points to the start
423 // of the "]]" closing the expression so account for it in computing the
424 // index of the first unparsed character.
425 PatternStr = UnparsedPatternStr.substr(End + 2);
427 bool IsDefinition = false;
428 bool SubstNeeded = false;
429 // Whether the substitution block is a legacy use of @LINE with string
430 // substitution block syntax.
431 bool IsLegacyLineExpr = false;
432 StringRef DefName;
433 StringRef SubstStr;
434 StringRef MatchRegexp;
435 size_t SubstInsertIdx = RegExStr.size();
437 // Parse string variable or legacy @LINE expression.
438 if (!IsNumBlock) {
439 size_t VarEndIdx = MatchStr.find(":");
440 size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
441 if (SpacePos != StringRef::npos) {
442 SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos),
443 SourceMgr::DK_Error, "unexpected whitespace");
444 return true;
447 // Get the name (e.g. "foo") and verify it is well formed.
448 StringRef OrigMatchStr = MatchStr;
449 Expected<FileCheckPattern::VariableProperties> ParseVarResult =
450 parseVariable(MatchStr, SM);
451 if (!ParseVarResult) {
452 logAllUnhandledErrors(ParseVarResult.takeError(), errs());
453 return true;
455 StringRef Name = ParseVarResult->Name;
456 bool IsPseudo = ParseVarResult->IsPseudo;
458 IsDefinition = (VarEndIdx != StringRef::npos);
459 SubstNeeded = !IsDefinition;
460 if (IsDefinition) {
461 if ((IsPseudo || !MatchStr.consume_front(":"))) {
462 SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
463 SourceMgr::DK_Error,
464 "invalid name in string variable definition");
465 return true;
468 // Detect collisions between string and numeric variables when the
469 // former is created later than the latter.
470 if (Context->GlobalNumericVariableTable.find(Name) !=
471 Context->GlobalNumericVariableTable.end()) {
472 SM.PrintMessage(
473 SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
474 "numeric variable with name '" + Name + "' already exists");
475 return true;
477 DefName = Name;
478 MatchRegexp = MatchStr;
479 } else {
480 if (IsPseudo) {
481 MatchStr = OrigMatchStr;
482 IsLegacyLineExpr = IsNumBlock = true;
483 } else
484 SubstStr = Name;
488 // Parse numeric substitution block.
489 std::unique_ptr<FileCheckExpressionAST> ExpressionAST;
490 Optional<FileCheckNumericVariable *> DefinedNumericVariable;
491 if (IsNumBlock) {
492 Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
493 parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable,
494 IsLegacyLineExpr, LineNumber, Context,
495 SM);
496 if (!ParseResult) {
497 logAllUnhandledErrors(ParseResult.takeError(), errs());
498 return true;
500 ExpressionAST = std::move(*ParseResult);
501 SubstNeeded = ExpressionAST != nullptr;
502 if (DefinedNumericVariable) {
503 IsDefinition = true;
504 DefName = (*DefinedNumericVariable)->getName();
506 if (SubstNeeded)
507 SubstStr = MatchStr;
508 else
509 MatchRegexp = "[0-9]+";
512 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
513 if (IsDefinition) {
514 RegExStr += '(';
515 ++SubstInsertIdx;
517 if (IsNumBlock) {
518 FileCheckNumericVariableMatch NumericVariableDefinition = {
519 *DefinedNumericVariable, CurParen};
520 NumericVariableDefs[DefName] = NumericVariableDefinition;
521 // This store is done here rather than in match() to allow
522 // parseNumericVariableUse() to get the pointer to the class instance
523 // of the right variable definition corresponding to a given numeric
524 // variable use.
525 Context->GlobalNumericVariableTable[DefName] =
526 *DefinedNumericVariable;
527 } else {
528 VariableDefs[DefName] = CurParen;
529 // Mark string variable as defined to detect collisions between
530 // string and numeric variables in parseNumericVariableUse() and
531 // defineCmdlineVariables() when the latter is created later than the
532 // former. We cannot reuse GlobalVariableTable for this by populating
533 // it with an empty string since we would then lose the ability to
534 // detect the use of an undefined variable in match().
535 Context->DefinedVariableTable[DefName] = true;
538 ++CurParen;
541 if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
542 return true;
544 if (IsDefinition)
545 RegExStr += ')';
547 // Handle substitutions: [[foo]] and [[#<foo expr>]].
548 if (SubstNeeded) {
549 // Handle substitution of string variables that were defined earlier on
550 // the same line by emitting a backreference. Expressions do not
551 // support substituting a numeric variable defined on the same line.
552 if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
553 unsigned CaptureParenGroup = VariableDefs[SubstStr];
554 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
555 SM.PrintMessage(SMLoc::getFromPointer(SubstStr.data()),
556 SourceMgr::DK_Error,
557 "Can't back-reference more than 9 variables");
558 return true;
560 AddBackrefToRegEx(CaptureParenGroup);
561 } else {
562 // Handle substitution of string variables ([[<var>]]) defined in
563 // previous CHECK patterns, and substitution of expressions.
564 FileCheckSubstitution *Substitution =
565 IsNumBlock
566 ? Context->makeNumericSubstitution(
567 SubstStr, std::move(ExpressionAST), SubstInsertIdx)
568 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
569 Substitutions.push_back(Substitution);
574 // Handle fixed string matches.
575 // Find the end, which is the start of the next regex.
576 size_t FixedMatchEnd = PatternStr.find("{{");
577 FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
578 RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
579 PatternStr = PatternStr.substr(FixedMatchEnd);
582 if (MatchFullLinesHere) {
583 if (!Req.NoCanonicalizeWhiteSpace)
584 RegExStr += " *";
585 RegExStr += '$';
588 return false;
591 bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
592 Regex R(RS);
593 std::string Error;
594 if (!R.isValid(Error)) {
595 SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
596 "invalid regex: " + Error);
597 return true;
600 RegExStr += RS.str();
601 CurParen += R.getNumMatches();
602 return false;
605 void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) {
606 assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
607 std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
608 RegExStr += Backref;
611 Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
612 const SourceMgr &SM) const {
613 // If this is the EOF pattern, match it immediately.
614 if (CheckTy == Check::CheckEOF) {
615 MatchLen = 0;
616 return Buffer.size();
619 // If this is a fixed string pattern, just match it now.
620 if (!FixedStr.empty()) {
621 MatchLen = FixedStr.size();
622 size_t Pos = Buffer.find(FixedStr);
623 if (Pos == StringRef::npos)
624 return make_error<FileCheckNotFoundError>();
625 return Pos;
628 // Regex match.
630 // If there are substitutions, we need to create a temporary string with the
631 // actual value.
632 StringRef RegExToMatch = RegExStr;
633 std::string TmpStr;
634 if (!Substitutions.empty()) {
635 TmpStr = RegExStr;
636 if (LineNumber)
637 Context->LineVariable->setValue(*LineNumber);
639 size_t InsertOffset = 0;
640 // Substitute all string variables and expressions whose values are only
641 // now known. Use of string variables defined on the same line are handled
642 // by back-references.
643 for (const auto &Substitution : Substitutions) {
644 // Substitute and check for failure (e.g. use of undefined variable).
645 Expected<std::string> Value = Substitution->getResult();
646 if (!Value)
647 return Value.takeError();
649 // Plop it into the regex at the adjusted offset.
650 TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset,
651 Value->begin(), Value->end());
652 InsertOffset += Value->size();
655 // Match the newly constructed regex.
656 RegExToMatch = TmpStr;
659 SmallVector<StringRef, 4> MatchInfo;
660 if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
661 return make_error<FileCheckNotFoundError>();
663 // Successful regex match.
664 assert(!MatchInfo.empty() && "Didn't get any match");
665 StringRef FullMatch = MatchInfo[0];
667 // If this defines any string variables, remember their values.
668 for (const auto &VariableDef : VariableDefs) {
669 assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
670 Context->GlobalVariableTable[VariableDef.first] =
671 MatchInfo[VariableDef.second];
674 // If this defines any numeric variables, remember their values.
675 for (const auto &NumericVariableDef : NumericVariableDefs) {
676 const FileCheckNumericVariableMatch &NumericVariableMatch =
677 NumericVariableDef.getValue();
678 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
679 assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");
680 FileCheckNumericVariable *DefinedNumericVariable =
681 NumericVariableMatch.DefinedNumericVariable;
683 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
684 uint64_t Val;
685 if (MatchedValue.getAsInteger(10, Val))
686 return FileCheckErrorDiagnostic::get(SM, MatchedValue,
687 "Unable to represent numeric value");
688 DefinedNumericVariable->setValue(Val);
691 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
692 // the required preceding newline, which is consumed by the pattern in the
693 // case of CHECK-EMPTY but not CHECK-NEXT.
694 size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
695 MatchLen = FullMatch.size() - MatchStartSkip;
696 return FullMatch.data() - Buffer.data() + MatchStartSkip;
699 unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer) const {
700 // Just compute the number of matching characters. For regular expressions, we
701 // just compare against the regex itself and hope for the best.
703 // FIXME: One easy improvement here is have the regex lib generate a single
704 // example regular expression which matches, and use that as the example
705 // string.
706 StringRef ExampleString(FixedStr);
707 if (ExampleString.empty())
708 ExampleString = RegExStr;
710 // Only compare up to the first line in the buffer, or the string size.
711 StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
712 BufferPrefix = BufferPrefix.split('\n').first;
713 return BufferPrefix.edit_distance(ExampleString);
716 void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
717 SMRange MatchRange) const {
718 // Print what we know about substitutions.
719 if (!Substitutions.empty()) {
720 for (const auto &Substitution : Substitutions) {
721 SmallString<256> Msg;
722 raw_svector_ostream OS(Msg);
723 Expected<std::string> MatchedValue = Substitution->getResult();
725 // Substitution failed or is not known at match time, print the undefined
726 // variables it uses.
727 if (!MatchedValue) {
728 bool UndefSeen = false;
729 handleAllErrors(MatchedValue.takeError(),
730 [](const FileCheckNotFoundError &E) {},
731 // Handled in PrintNoMatch().
732 [](const FileCheckErrorDiagnostic &E) {},
733 [&](const FileCheckUndefVarError &E) {
734 if (!UndefSeen) {
735 OS << "uses undefined variable(s):";
736 UndefSeen = true;
738 OS << " ";
739 E.log(OS);
741 } else {
742 // Substitution succeeded. Print substituted value.
743 OS << "with \"";
744 OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";
745 OS.write_escaped(*MatchedValue) << "\"";
748 if (MatchRange.isValid())
749 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
750 {MatchRange});
751 else
752 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
753 SourceMgr::DK_Note, OS.str());
758 static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy,
759 const SourceMgr &SM, SMLoc Loc,
760 Check::FileCheckType CheckTy,
761 StringRef Buffer, size_t Pos, size_t Len,
762 std::vector<FileCheckDiag> *Diags,
763 bool AdjustPrevDiag = false) {
764 SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
765 SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
766 SMRange Range(Start, End);
767 if (Diags) {
768 if (AdjustPrevDiag)
769 Diags->rbegin()->MatchTy = MatchTy;
770 else
771 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
773 return Range;
776 void FileCheckPattern::printFuzzyMatch(
777 const SourceMgr &SM, StringRef Buffer,
778 std::vector<FileCheckDiag> *Diags) const {
779 // Attempt to find the closest/best fuzzy match. Usually an error happens
780 // because some string in the output didn't exactly match. In these cases, we
781 // would like to show the user a best guess at what "should have" matched, to
782 // save them having to actually check the input manually.
783 size_t NumLinesForward = 0;
784 size_t Best = StringRef::npos;
785 double BestQuality = 0;
787 // Use an arbitrary 4k limit on how far we will search.
788 for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
789 if (Buffer[i] == '\n')
790 ++NumLinesForward;
792 // Patterns have leading whitespace stripped, so skip whitespace when
793 // looking for something which looks like a pattern.
794 if (Buffer[i] == ' ' || Buffer[i] == '\t')
795 continue;
797 // Compute the "quality" of this match as an arbitrary combination of the
798 // match distance and the number of lines skipped to get to this match.
799 unsigned Distance = computeMatchDistance(Buffer.substr(i));
800 double Quality = Distance + (NumLinesForward / 100.);
802 if (Quality < BestQuality || Best == StringRef::npos) {
803 Best = i;
804 BestQuality = Quality;
808 // Print the "possible intended match here" line if we found something
809 // reasonable and not equal to what we showed in the "scanning from here"
810 // line.
811 if (Best && Best != StringRef::npos && BestQuality < 50) {
812 SMRange MatchRange =
813 ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(),
814 getCheckTy(), Buffer, Best, 0, Diags);
815 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,
816 "possible intended match here");
818 // FIXME: If we wanted to be really friendly we would show why the match
819 // failed, as it can be hard to spot simple one character differences.
823 Expected<StringRef>
824 FileCheckPatternContext::getPatternVarValue(StringRef VarName) {
825 auto VarIter = GlobalVariableTable.find(VarName);
826 if (VarIter == GlobalVariableTable.end())
827 return make_error<FileCheckUndefVarError>(VarName);
829 return VarIter->second;
832 template <class... Types>
833 FileCheckNumericVariable *
834 FileCheckPatternContext::makeNumericVariable(Types... args) {
835 NumericVariables.push_back(
836 std::make_unique<FileCheckNumericVariable>(args...));
837 return NumericVariables.back().get();
840 FileCheckSubstitution *
841 FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
842 size_t InsertIdx) {
843 Substitutions.push_back(
844 std::make_unique<FileCheckStringSubstitution>(this, VarName, InsertIdx));
845 return Substitutions.back().get();
848 FileCheckSubstitution *FileCheckPatternContext::makeNumericSubstitution(
849 StringRef ExpressionStr,
850 std::unique_ptr<FileCheckExpressionAST> ExpressionAST, size_t InsertIdx) {
851 Substitutions.push_back(std::make_unique<FileCheckNumericSubstitution>(
852 this, ExpressionStr, std::move(ExpressionAST), InsertIdx));
853 return Substitutions.back().get();
856 size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
857 // Offset keeps track of the current offset within the input Str
858 size_t Offset = 0;
859 // [...] Nesting depth
860 size_t BracketDepth = 0;
862 while (!Str.empty()) {
863 if (Str.startswith("]]") && BracketDepth == 0)
864 return Offset;
865 if (Str[0] == '\\') {
866 // Backslash escapes the next char within regexes, so skip them both.
867 Str = Str.substr(2);
868 Offset += 2;
869 } else {
870 switch (Str[0]) {
871 default:
872 break;
873 case '[':
874 BracketDepth++;
875 break;
876 case ']':
877 if (BracketDepth == 0) {
878 SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
879 SourceMgr::DK_Error,
880 "missing closing \"]\" for regex variable");
881 exit(1);
883 BracketDepth--;
884 break;
886 Str = Str.substr(1);
887 Offset++;
891 return StringRef::npos;
894 StringRef FileCheck::CanonicalizeFile(MemoryBuffer &MB,
895 SmallVectorImpl<char> &OutputBuffer) {
896 OutputBuffer.reserve(MB.getBufferSize());
898 for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
899 Ptr != End; ++Ptr) {
900 // Eliminate trailing dosish \r.
901 if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
902 continue;
905 // If current char is not a horizontal whitespace or if horizontal
906 // whitespace canonicalization is disabled, dump it to output as is.
907 if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
908 OutputBuffer.push_back(*Ptr);
909 continue;
912 // Otherwise, add one space and advance over neighboring space.
913 OutputBuffer.push_back(' ');
914 while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
915 ++Ptr;
918 // Add a null byte and then return all but that byte.
919 OutputBuffer.push_back('\0');
920 return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
923 FileCheckDiag::FileCheckDiag(const SourceMgr &SM,
924 const Check::FileCheckType &CheckTy,
925 SMLoc CheckLoc, MatchType MatchTy,
926 SMRange InputRange)
927 : CheckTy(CheckTy), MatchTy(MatchTy) {
928 auto Start = SM.getLineAndColumn(InputRange.Start);
929 auto End = SM.getLineAndColumn(InputRange.End);
930 InputStartLine = Start.first;
931 InputStartCol = Start.second;
932 InputEndLine = End.first;
933 InputEndCol = End.second;
934 Start = SM.getLineAndColumn(CheckLoc);
935 CheckLine = Start.first;
936 CheckCol = Start.second;
939 static bool IsPartOfWord(char c) {
940 return (isalnum(c) || c == '-' || c == '_');
943 Check::FileCheckType &Check::FileCheckType::setCount(int C) {
944 assert(Count > 0 && "zero and negative counts are not supported");
945 assert((C == 1 || Kind == CheckPlain) &&
946 "count supported only for plain CHECK directives");
947 Count = C;
948 return *this;
951 std::string Check::FileCheckType::getDescription(StringRef Prefix) const {
952 switch (Kind) {
953 case Check::CheckNone:
954 return "invalid";
955 case Check::CheckPlain:
956 if (Count > 1)
957 return Prefix.str() + "-COUNT";
958 return Prefix;
959 case Check::CheckNext:
960 return Prefix.str() + "-NEXT";
961 case Check::CheckSame:
962 return Prefix.str() + "-SAME";
963 case Check::CheckNot:
964 return Prefix.str() + "-NOT";
965 case Check::CheckDAG:
966 return Prefix.str() + "-DAG";
967 case Check::CheckLabel:
968 return Prefix.str() + "-LABEL";
969 case Check::CheckEmpty:
970 return Prefix.str() + "-EMPTY";
971 case Check::CheckEOF:
972 return "implicit EOF";
973 case Check::CheckBadNot:
974 return "bad NOT";
975 case Check::CheckBadCount:
976 return "bad COUNT";
978 llvm_unreachable("unknown FileCheckType");
981 static std::pair<Check::FileCheckType, StringRef>
982 FindCheckType(StringRef Buffer, StringRef Prefix) {
983 if (Buffer.size() <= Prefix.size())
984 return {Check::CheckNone, StringRef()};
986 char NextChar = Buffer[Prefix.size()];
988 StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
989 // Verify that the : is present after the prefix.
990 if (NextChar == ':')
991 return {Check::CheckPlain, Rest};
993 if (NextChar != '-')
994 return {Check::CheckNone, StringRef()};
996 if (Rest.consume_front("COUNT-")) {
997 int64_t Count;
998 if (Rest.consumeInteger(10, Count))
999 // Error happened in parsing integer.
1000 return {Check::CheckBadCount, Rest};
1001 if (Count <= 0 || Count > INT32_MAX)
1002 return {Check::CheckBadCount, Rest};
1003 if (!Rest.consume_front(":"))
1004 return {Check::CheckBadCount, Rest};
1005 return {Check::FileCheckType(Check::CheckPlain).setCount(Count), Rest};
1008 if (Rest.consume_front("NEXT:"))
1009 return {Check::CheckNext, Rest};
1011 if (Rest.consume_front("SAME:"))
1012 return {Check::CheckSame, Rest};
1014 if (Rest.consume_front("NOT:"))
1015 return {Check::CheckNot, Rest};
1017 if (Rest.consume_front("DAG:"))
1018 return {Check::CheckDAG, Rest};
1020 if (Rest.consume_front("LABEL:"))
1021 return {Check::CheckLabel, Rest};
1023 if (Rest.consume_front("EMPTY:"))
1024 return {Check::CheckEmpty, Rest};
1026 // You can't combine -NOT with another suffix.
1027 if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
1028 Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
1029 Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
1030 Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
1031 return {Check::CheckBadNot, Rest};
1033 return {Check::CheckNone, Rest};
1036 // From the given position, find the next character after the word.
1037 static size_t SkipWord(StringRef Str, size_t Loc) {
1038 while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
1039 ++Loc;
1040 return Loc;
1043 /// Searches the buffer for the first prefix in the prefix regular expression.
1045 /// This searches the buffer using the provided regular expression, however it
1046 /// enforces constraints beyond that:
1047 /// 1) The found prefix must not be a suffix of something that looks like
1048 /// a valid prefix.
1049 /// 2) The found prefix must be followed by a valid check type suffix using \c
1050 /// FindCheckType above.
1052 /// \returns a pair of StringRefs into the Buffer, which combines:
1053 /// - the first match of the regular expression to satisfy these two is
1054 /// returned,
1055 /// otherwise an empty StringRef is returned to indicate failure.
1056 /// - buffer rewound to the location right after parsed suffix, for parsing
1057 /// to continue from
1059 /// If this routine returns a valid prefix, it will also shrink \p Buffer to
1060 /// start at the beginning of the returned prefix, increment \p LineNumber for
1061 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1062 /// check found by examining the suffix.
1064 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1065 /// is unspecified.
1066 static std::pair<StringRef, StringRef>
1067 FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
1068 unsigned &LineNumber, Check::FileCheckType &CheckTy) {
1069 SmallVector<StringRef, 2> Matches;
1071 while (!Buffer.empty()) {
1072 // Find the first (longest) match using the RE.
1073 if (!PrefixRE.match(Buffer, &Matches))
1074 // No match at all, bail.
1075 return {StringRef(), StringRef()};
1077 StringRef Prefix = Matches[0];
1078 Matches.clear();
1080 assert(Prefix.data() >= Buffer.data() &&
1081 Prefix.data() < Buffer.data() + Buffer.size() &&
1082 "Prefix doesn't start inside of buffer!");
1083 size_t Loc = Prefix.data() - Buffer.data();
1084 StringRef Skipped = Buffer.substr(0, Loc);
1085 Buffer = Buffer.drop_front(Loc);
1086 LineNumber += Skipped.count('\n');
1088 // Check that the matched prefix isn't a suffix of some other check-like
1089 // word.
1090 // FIXME: This is a very ad-hoc check. it would be better handled in some
1091 // other way. Among other things it seems hard to distinguish between
1092 // intentional and unintentional uses of this feature.
1093 if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
1094 // Now extract the type.
1095 StringRef AfterSuffix;
1096 std::tie(CheckTy, AfterSuffix) = FindCheckType(Buffer, Prefix);
1098 // If we've found a valid check type for this prefix, we're done.
1099 if (CheckTy != Check::CheckNone)
1100 return {Prefix, AfterSuffix};
1103 // If we didn't successfully find a prefix, we need to skip this invalid
1104 // prefix and continue scanning. We directly skip the prefix that was
1105 // matched and any additional parts of that check-like word.
1106 Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
1109 // We ran out of buffer while skipping partial matches so give up.
1110 return {StringRef(), StringRef()};
1113 void FileCheckPatternContext::createLineVariable() {
1114 assert(!LineVariable && "@LINE pseudo numeric variable already created");
1115 StringRef LineName = "@LINE";
1116 LineVariable = makeNumericVariable(LineName);
1117 GlobalNumericVariableTable[LineName] = LineVariable;
1120 FileCheck::FileCheck(FileCheckRequest Req)
1121 : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()),
1122 CheckStrings(std::make_unique<std::vector<FileCheckString>>()) {}
1124 FileCheck::~FileCheck() = default;
1126 bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
1127 Regex &PrefixRE) {
1128 Error DefineError =
1129 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1130 if (DefineError) {
1131 logAllUnhandledErrors(std::move(DefineError), errs());
1132 return true;
1135 PatternContext->createLineVariable();
1137 std::vector<FileCheckPattern> ImplicitNegativeChecks;
1138 for (const auto &PatternString : Req.ImplicitCheckNot) {
1139 // Create a buffer with fake command line content in order to display the
1140 // command line option responsible for the specific implicit CHECK-NOT.
1141 std::string Prefix = "-implicit-check-not='";
1142 std::string Suffix = "'";
1143 std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
1144 Prefix + PatternString + Suffix, "command line");
1146 StringRef PatternInBuffer =
1147 CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
1148 SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
1150 ImplicitNegativeChecks.push_back(
1151 FileCheckPattern(Check::CheckNot, PatternContext.get()));
1152 ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
1153 "IMPLICIT-CHECK", SM, Req);
1156 std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks;
1158 // LineNumber keeps track of the line on which CheckPrefix instances are
1159 // found.
1160 unsigned LineNumber = 1;
1162 while (1) {
1163 Check::FileCheckType CheckTy;
1165 // See if a prefix occurs in the memory buffer.
1166 StringRef UsedPrefix;
1167 StringRef AfterSuffix;
1168 std::tie(UsedPrefix, AfterSuffix) =
1169 FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, CheckTy);
1170 if (UsedPrefix.empty())
1171 break;
1172 assert(UsedPrefix.data() == Buffer.data() &&
1173 "Failed to move Buffer's start forward, or pointed prefix outside "
1174 "of the buffer!");
1175 assert(AfterSuffix.data() >= Buffer.data() &&
1176 AfterSuffix.data() < Buffer.data() + Buffer.size() &&
1177 "Parsing after suffix doesn't start inside of buffer!");
1179 // Location to use for error messages.
1180 const char *UsedPrefixStart = UsedPrefix.data();
1182 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1183 // suffix was processed).
1184 Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size())
1185 : AfterSuffix;
1187 // Complain about useful-looking but unsupported suffixes.
1188 if (CheckTy == Check::CheckBadNot) {
1189 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
1190 "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
1191 return true;
1194 // Complain about invalid count specification.
1195 if (CheckTy == Check::CheckBadCount) {
1196 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
1197 "invalid count in -COUNT specification on prefix '" +
1198 UsedPrefix + "'");
1199 return true;
1202 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1203 // leading whitespace.
1204 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1205 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
1207 // Scan ahead to the end of line.
1208 size_t EOL = Buffer.find_first_of("\n\r");
1210 // Remember the location of the start of the pattern, for diagnostics.
1211 SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
1213 // Parse the pattern.
1214 FileCheckPattern P(CheckTy, PatternContext.get(), LineNumber);
1215 if (P.parsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, Req))
1216 return true;
1218 // Verify that CHECK-LABEL lines do not define or use variables
1219 if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
1220 SM.PrintMessage(
1221 SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
1222 "found '" + UsedPrefix + "-LABEL:'"
1223 " with variable definition or use");
1224 return true;
1227 Buffer = Buffer.substr(EOL);
1229 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1230 if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
1231 CheckTy == Check::CheckEmpty) &&
1232 CheckStrings->empty()) {
1233 StringRef Type = CheckTy == Check::CheckNext
1234 ? "NEXT"
1235 : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
1236 SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
1237 SourceMgr::DK_Error,
1238 "found '" + UsedPrefix + "-" + Type +
1239 "' without previous '" + UsedPrefix + ": line");
1240 return true;
1243 // Handle CHECK-DAG/-NOT.
1244 if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
1245 DagNotMatches.push_back(P);
1246 continue;
1249 // Okay, add the string we captured to the output vector and move on.
1250 CheckStrings->emplace_back(P, UsedPrefix, PatternLoc);
1251 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
1252 DagNotMatches = ImplicitNegativeChecks;
1255 // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
1256 // prefix as a filler for the error message.
1257 if (!DagNotMatches.empty()) {
1258 CheckStrings->emplace_back(
1259 FileCheckPattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
1260 *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()));
1261 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
1264 if (CheckStrings->empty()) {
1265 errs() << "error: no check strings found with prefix"
1266 << (Req.CheckPrefixes.size() > 1 ? "es " : " ");
1267 auto I = Req.CheckPrefixes.begin();
1268 auto E = Req.CheckPrefixes.end();
1269 if (I != E) {
1270 errs() << "\'" << *I << ":'";
1271 ++I;
1273 for (; I != E; ++I)
1274 errs() << ", \'" << *I << ":'";
1276 errs() << '\n';
1277 return true;
1280 return false;
1283 static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
1284 StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,
1285 int MatchedCount, StringRef Buffer, size_t MatchPos,
1286 size_t MatchLen, const FileCheckRequest &Req,
1287 std::vector<FileCheckDiag> *Diags) {
1288 bool PrintDiag = true;
1289 if (ExpectedMatch) {
1290 if (!Req.Verbose)
1291 return;
1292 if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
1293 return;
1294 // Due to their verbosity, we don't print verbose diagnostics here if we're
1295 // gathering them for a different rendering, but we always print other
1296 // diagnostics.
1297 PrintDiag = !Diags;
1299 SMRange MatchRange = ProcessMatchResult(
1300 ExpectedMatch ? FileCheckDiag::MatchFoundAndExpected
1301 : FileCheckDiag::MatchFoundButExcluded,
1302 SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
1303 if (!PrintDiag)
1304 return;
1306 std::string Message = formatv("{0}: {1} string found in input",
1307 Pat.getCheckTy().getDescription(Prefix),
1308 (ExpectedMatch ? "expected" : "excluded"))
1309 .str();
1310 if (Pat.getCount() > 1)
1311 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
1313 SM.PrintMessage(
1314 Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
1315 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
1316 {MatchRange});
1317 Pat.printSubstitutions(SM, Buffer, MatchRange);
1320 static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
1321 const FileCheckString &CheckStr, int MatchedCount,
1322 StringRef Buffer, size_t MatchPos, size_t MatchLen,
1323 FileCheckRequest &Req,
1324 std::vector<FileCheckDiag> *Diags) {
1325 PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
1326 MatchedCount, Buffer, MatchPos, MatchLen, Req, Diags);
1329 static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
1330 StringRef Prefix, SMLoc Loc,
1331 const FileCheckPattern &Pat, int MatchedCount,
1332 StringRef Buffer, bool VerboseVerbose,
1333 std::vector<FileCheckDiag> *Diags, Error MatchErrors) {
1334 assert(MatchErrors && "Called on successful match");
1335 bool PrintDiag = true;
1336 if (!ExpectedMatch) {
1337 if (!VerboseVerbose) {
1338 consumeError(std::move(MatchErrors));
1339 return;
1341 // Due to their verbosity, we don't print verbose diagnostics here if we're
1342 // gathering them for a different rendering, but we always print other
1343 // diagnostics.
1344 PrintDiag = !Diags;
1347 // If the current position is at the end of a line, advance to the start of
1348 // the next line.
1349 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
1350 SMRange SearchRange = ProcessMatchResult(
1351 ExpectedMatch ? FileCheckDiag::MatchNoneButExpected
1352 : FileCheckDiag::MatchNoneAndExcluded,
1353 SM, Loc, Pat.getCheckTy(), Buffer, 0, Buffer.size(), Diags);
1354 if (!PrintDiag) {
1355 consumeError(std::move(MatchErrors));
1356 return;
1359 MatchErrors =
1360 handleErrors(std::move(MatchErrors),
1361 [](const FileCheckErrorDiagnostic &E) { E.log(errs()); });
1363 // No problem matching the string per se.
1364 if (!MatchErrors)
1365 return;
1366 consumeError(std::move(MatchErrors));
1368 // Print "not found" diagnostic.
1369 std::string Message = formatv("{0}: {1} string not found in input",
1370 Pat.getCheckTy().getDescription(Prefix),
1371 (ExpectedMatch ? "expected" : "excluded"))
1372 .str();
1373 if (Pat.getCount() > 1)
1374 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
1375 SM.PrintMessage(
1376 Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message);
1378 // Print the "scanning from here" line.
1379 SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here");
1381 // Allow the pattern to print additional information if desired.
1382 Pat.printSubstitutions(SM, Buffer);
1384 if (ExpectedMatch)
1385 Pat.printFuzzyMatch(SM, Buffer, Diags);
1388 static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
1389 const FileCheckString &CheckStr, int MatchedCount,
1390 StringRef Buffer, bool VerboseVerbose,
1391 std::vector<FileCheckDiag> *Diags, Error MatchErrors) {
1392 PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
1393 MatchedCount, Buffer, VerboseVerbose, Diags,
1394 std::move(MatchErrors));
1397 /// Counts the number of newlines in the specified range.
1398 static unsigned CountNumNewlinesBetween(StringRef Range,
1399 const char *&FirstNewLine) {
1400 unsigned NumNewLines = 0;
1401 while (1) {
1402 // Scan for newline.
1403 Range = Range.substr(Range.find_first_of("\n\r"));
1404 if (Range.empty())
1405 return NumNewLines;
1407 ++NumNewLines;
1409 // Handle \n\r and \r\n as a single newline.
1410 if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
1411 (Range[0] != Range[1]))
1412 Range = Range.substr(1);
1413 Range = Range.substr(1);
1415 if (NumNewLines == 1)
1416 FirstNewLine = Range.begin();
1420 size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
1421 bool IsLabelScanMode, size_t &MatchLen,
1422 FileCheckRequest &Req,
1423 std::vector<FileCheckDiag> *Diags) const {
1424 size_t LastPos = 0;
1425 std::vector<const FileCheckPattern *> NotStrings;
1427 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1428 // bounds; we have not processed variable definitions within the bounded block
1429 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1430 // over the block again (including the last CHECK-LABEL) in normal mode.
1431 if (!IsLabelScanMode) {
1432 // Match "dag strings" (with mixed "not strings" if any).
1433 LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
1434 if (LastPos == StringRef::npos)
1435 return StringRef::npos;
1438 // Match itself from the last position after matching CHECK-DAG.
1439 size_t LastMatchEnd = LastPos;
1440 size_t FirstMatchPos = 0;
1441 // Go match the pattern Count times. Majority of patterns only match with
1442 // count 1 though.
1443 assert(Pat.getCount() != 0 && "pattern count can not be zero");
1444 for (int i = 1; i <= Pat.getCount(); i++) {
1445 StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
1446 size_t CurrentMatchLen;
1447 // get a match at current start point
1448 Expected<size_t> MatchResult = Pat.match(MatchBuffer, CurrentMatchLen, SM);
1450 // report
1451 if (!MatchResult) {
1452 PrintNoMatch(true, SM, *this, i, MatchBuffer, Req.VerboseVerbose, Diags,
1453 MatchResult.takeError());
1454 return StringRef::npos;
1456 size_t MatchPos = *MatchResult;
1457 PrintMatch(true, SM, *this, i, MatchBuffer, MatchPos, CurrentMatchLen, Req,
1458 Diags);
1459 if (i == 1)
1460 FirstMatchPos = LastPos + MatchPos;
1462 // move start point after the match
1463 LastMatchEnd += MatchPos + CurrentMatchLen;
1465 // Full match len counts from first match pos.
1466 MatchLen = LastMatchEnd - FirstMatchPos;
1468 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1469 // or CHECK-NOT
1470 if (!IsLabelScanMode) {
1471 size_t MatchPos = FirstMatchPos - LastPos;
1472 StringRef MatchBuffer = Buffer.substr(LastPos);
1473 StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
1475 // If this check is a "CHECK-NEXT", verify that the previous match was on
1476 // the previous line (i.e. that there is one newline between them).
1477 if (CheckNext(SM, SkippedRegion)) {
1478 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
1479 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
1480 Diags, Req.Verbose);
1481 return StringRef::npos;
1484 // If this check is a "CHECK-SAME", verify that the previous match was on
1485 // the same line (i.e. that there is no newline between them).
1486 if (CheckSame(SM, SkippedRegion)) {
1487 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
1488 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
1489 Diags, Req.Verbose);
1490 return StringRef::npos;
1493 // If this match had "not strings", verify that they don't exist in the
1494 // skipped region.
1495 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
1496 return StringRef::npos;
1499 return FirstMatchPos;
1502 bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
1503 if (Pat.getCheckTy() != Check::CheckNext &&
1504 Pat.getCheckTy() != Check::CheckEmpty)
1505 return false;
1507 Twine CheckName =
1508 Prefix +
1509 Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
1511 // Count the number of newlines between the previous match and this one.
1512 const char *FirstNewLine = nullptr;
1513 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1515 if (NumNewLines == 0) {
1516 SM.PrintMessage(Loc, SourceMgr::DK_Error,
1517 CheckName + ": is on the same line as previous match");
1518 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1519 "'next' match was here");
1520 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1521 "previous match ended here");
1522 return true;
1525 if (NumNewLines != 1) {
1526 SM.PrintMessage(Loc, SourceMgr::DK_Error,
1527 CheckName +
1528 ": is not on the line after the previous match");
1529 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1530 "'next' match was here");
1531 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1532 "previous match ended here");
1533 SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
1534 "non-matching line after previous match is here");
1535 return true;
1538 return false;
1541 bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
1542 if (Pat.getCheckTy() != Check::CheckSame)
1543 return false;
1545 // Count the number of newlines between the previous match and this one.
1546 const char *FirstNewLine = nullptr;
1547 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
1549 if (NumNewLines != 0) {
1550 SM.PrintMessage(Loc, SourceMgr::DK_Error,
1551 Prefix +
1552 "-SAME: is not on the same line as the previous match");
1553 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
1554 "'next' match was here");
1555 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
1556 "previous match ended here");
1557 return true;
1560 return false;
1563 bool FileCheckString::CheckNot(
1564 const SourceMgr &SM, StringRef Buffer,
1565 const std::vector<const FileCheckPattern *> &NotStrings,
1566 const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const {
1567 for (const FileCheckPattern *Pat : NotStrings) {
1568 assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
1570 size_t MatchLen = 0;
1571 Expected<size_t> MatchResult = Pat->match(Buffer, MatchLen, SM);
1573 if (!MatchResult) {
1574 PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer,
1575 Req.VerboseVerbose, Diags, MatchResult.takeError());
1576 continue;
1578 size_t Pos = *MatchResult;
1580 PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, Pos, MatchLen,
1581 Req, Diags);
1583 return true;
1586 return false;
1589 size_t
1590 FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
1591 std::vector<const FileCheckPattern *> &NotStrings,
1592 const FileCheckRequest &Req,
1593 std::vector<FileCheckDiag> *Diags) const {
1594 if (DagNotStrings.empty())
1595 return 0;
1597 // The start of the search range.
1598 size_t StartPos = 0;
1600 struct MatchRange {
1601 size_t Pos;
1602 size_t End;
1604 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
1605 // ranges are erased from this list once they are no longer in the search
1606 // range.
1607 std::list<MatchRange> MatchRanges;
1609 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
1610 // group, so we don't use a range-based for loop here.
1611 for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
1612 PatItr != PatEnd; ++PatItr) {
1613 const FileCheckPattern &Pat = *PatItr;
1614 assert((Pat.getCheckTy() == Check::CheckDAG ||
1615 Pat.getCheckTy() == Check::CheckNot) &&
1616 "Invalid CHECK-DAG or CHECK-NOT!");
1618 if (Pat.getCheckTy() == Check::CheckNot) {
1619 NotStrings.push_back(&Pat);
1620 continue;
1623 assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
1625 // CHECK-DAG always matches from the start.
1626 size_t MatchLen = 0, MatchPos = StartPos;
1628 // Search for a match that doesn't overlap a previous match in this
1629 // CHECK-DAG group.
1630 for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
1631 StringRef MatchBuffer = Buffer.substr(MatchPos);
1632 Expected<size_t> MatchResult = Pat.match(MatchBuffer, MatchLen, SM);
1633 // With a group of CHECK-DAGs, a single mismatching means the match on
1634 // that group of CHECK-DAGs fails immediately.
1635 if (!MatchResult) {
1636 PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer,
1637 Req.VerboseVerbose, Diags, MatchResult.takeError());
1638 return StringRef::npos;
1640 size_t MatchPosBuf = *MatchResult;
1641 // Re-calc it as the offset relative to the start of the original string.
1642 MatchPos += MatchPosBuf;
1643 if (Req.VerboseVerbose)
1644 PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,
1645 MatchLen, Req, Diags);
1646 MatchRange M{MatchPos, MatchPos + MatchLen};
1647 if (Req.AllowDeprecatedDagOverlap) {
1648 // We don't need to track all matches in this mode, so we just maintain
1649 // one match range that encompasses the current CHECK-DAG group's
1650 // matches.
1651 if (MatchRanges.empty())
1652 MatchRanges.insert(MatchRanges.end(), M);
1653 else {
1654 auto Block = MatchRanges.begin();
1655 Block->Pos = std::min(Block->Pos, M.Pos);
1656 Block->End = std::max(Block->End, M.End);
1658 break;
1660 // Iterate previous matches until overlapping match or insertion point.
1661 bool Overlap = false;
1662 for (; MI != ME; ++MI) {
1663 if (M.Pos < MI->End) {
1664 // !Overlap => New match has no overlap and is before this old match.
1665 // Overlap => New match overlaps this old match.
1666 Overlap = MI->Pos < M.End;
1667 break;
1670 if (!Overlap) {
1671 // Insert non-overlapping match into list.
1672 MatchRanges.insert(MI, M);
1673 break;
1675 if (Req.VerboseVerbose) {
1676 // Due to their verbosity, we don't print verbose diagnostics here if
1677 // we're gathering them for a different rendering, but we always print
1678 // other diagnostics.
1679 if (!Diags) {
1680 SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
1681 SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
1682 SMRange OldRange(OldStart, OldEnd);
1683 SM.PrintMessage(OldStart, SourceMgr::DK_Note,
1684 "match discarded, overlaps earlier DAG match here",
1685 {OldRange});
1686 } else
1687 Diags->rbegin()->MatchTy = FileCheckDiag::MatchFoundButDiscarded;
1689 MatchPos = MI->End;
1691 if (!Req.VerboseVerbose)
1692 PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,
1693 MatchLen, Req, Diags);
1695 // Handle the end of a CHECK-DAG group.
1696 if (std::next(PatItr) == PatEnd ||
1697 std::next(PatItr)->getCheckTy() == Check::CheckNot) {
1698 if (!NotStrings.empty()) {
1699 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
1700 // CHECK-DAG, verify that there are no 'not' strings occurred in that
1701 // region.
1702 StringRef SkippedRegion =
1703 Buffer.slice(StartPos, MatchRanges.begin()->Pos);
1704 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
1705 return StringRef::npos;
1706 // Clear "not strings".
1707 NotStrings.clear();
1709 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
1710 // end of this CHECK-DAG group's match range.
1711 StartPos = MatchRanges.rbegin()->End;
1712 // Don't waste time checking for (impossible) overlaps before that.
1713 MatchRanges.clear();
1717 return StartPos;
1720 // A check prefix must contain only alphanumeric, hyphens and underscores.
1721 static bool ValidateCheckPrefix(StringRef CheckPrefix) {
1722 static const Regex Validator("^[a-zA-Z0-9_-]*$");
1723 return Validator.match(CheckPrefix);
1726 bool FileCheck::ValidateCheckPrefixes() {
1727 StringSet<> PrefixSet;
1729 for (StringRef Prefix : Req.CheckPrefixes) {
1730 // Reject empty prefixes.
1731 if (Prefix == "")
1732 return false;
1734 if (!PrefixSet.insert(Prefix).second)
1735 return false;
1737 if (!ValidateCheckPrefix(Prefix))
1738 return false;
1741 return true;
1744 Regex FileCheck::buildCheckPrefixRegex() {
1745 // I don't think there's a way to specify an initial value for cl::list,
1746 // so if nothing was specified, add the default
1747 if (Req.CheckPrefixes.empty())
1748 Req.CheckPrefixes.push_back("CHECK");
1750 // We already validated the contents of CheckPrefixes so just concatenate
1751 // them as alternatives.
1752 SmallString<32> PrefixRegexStr;
1753 for (StringRef Prefix : Req.CheckPrefixes) {
1754 if (Prefix != Req.CheckPrefixes.front())
1755 PrefixRegexStr.push_back('|');
1757 PrefixRegexStr.append(Prefix);
1760 return Regex(PrefixRegexStr);
1763 Error FileCheckPatternContext::defineCmdlineVariables(
1764 std::vector<std::string> &CmdlineDefines, SourceMgr &SM) {
1765 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
1766 "Overriding defined variable with command-line variable definitions");
1768 if (CmdlineDefines.empty())
1769 return Error::success();
1771 // Create a string representing the vector of command-line definitions. Each
1772 // definition is on its own line and prefixed with a definition number to
1773 // clarify which definition a given diagnostic corresponds to.
1774 unsigned I = 0;
1775 Error Errs = Error::success();
1776 std::string CmdlineDefsDiag;
1777 SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;
1778 for (StringRef CmdlineDef : CmdlineDefines) {
1779 std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
1780 size_t EqIdx = CmdlineDef.find('=');
1781 if (EqIdx == StringRef::npos) {
1782 CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
1783 continue;
1785 // Numeric variable definition.
1786 if (CmdlineDef[0] == '#') {
1787 // Append a copy of the command-line definition adapted to use the same
1788 // format as in the input file to be able to reuse
1789 // parseNumericSubstitutionBlock.
1790 CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
1791 std::string SubstitutionStr = CmdlineDef;
1792 SubstitutionStr[EqIdx] = ':';
1793 CmdlineDefsIndices.push_back(
1794 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
1795 CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
1796 } else {
1797 CmdlineDefsDiag += DefPrefix;
1798 CmdlineDefsIndices.push_back(
1799 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
1800 CmdlineDefsDiag += (CmdlineDef + "\n").str();
1804 // Create a buffer with fake command line content in order to display
1805 // parsing diagnostic with location information and point to the
1806 // global definition with invalid syntax.
1807 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
1808 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");
1809 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
1810 SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
1812 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
1813 StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
1814 CmdlineDefIndices.second);
1815 if (CmdlineDef.empty()) {
1816 Errs = joinErrors(
1817 std::move(Errs),
1818 FileCheckErrorDiagnostic::get(
1819 SM, CmdlineDef, "missing equal sign in global definition"));
1820 continue;
1823 // Numeric variable definition.
1824 if (CmdlineDef[0] == '#') {
1825 // Now parse the definition both to check that the syntax is correct and
1826 // to create the necessary class instance.
1827 StringRef CmdlineDefExpr = CmdlineDef.substr(1);
1828 Optional<FileCheckNumericVariable *> DefinedNumericVariable;
1829 Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionASTResult =
1830 FileCheckPattern::parseNumericSubstitutionBlock(
1831 CmdlineDefExpr, DefinedNumericVariable, false, None, this, SM);
1832 if (!ExpressionASTResult) {
1833 Errs = joinErrors(std::move(Errs), ExpressionASTResult.takeError());
1834 continue;
1836 std::unique_ptr<FileCheckExpressionAST> ExpressionAST =
1837 std::move(*ExpressionASTResult);
1838 // Now evaluate the expression whose value this variable should be set
1839 // to, since the expression of a command-line variable definition should
1840 // only use variables defined earlier on the command-line. If not, this
1841 // is an error and we report it.
1842 Expected<uint64_t> Value = ExpressionAST->eval();
1843 if (!Value) {
1844 Errs = joinErrors(std::move(Errs), Value.takeError());
1845 continue;
1848 assert(DefinedNumericVariable && "No variable defined");
1849 (*DefinedNumericVariable)->setValue(*Value);
1851 // Record this variable definition.
1852 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
1853 *DefinedNumericVariable;
1854 } else {
1855 // String variable definition.
1856 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
1857 StringRef CmdlineName = CmdlineNameVal.first;
1858 StringRef OrigCmdlineName = CmdlineName;
1859 Expected<FileCheckPattern::VariableProperties> ParseVarResult =
1860 FileCheckPattern::parseVariable(CmdlineName, SM);
1861 if (!ParseVarResult) {
1862 Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());
1863 continue;
1865 // Check that CmdlineName does not denote a pseudo variable is only
1866 // composed of the parsed numeric variable. This catches cases like
1867 // "FOO+2" in a "FOO+2=10" definition.
1868 if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
1869 Errs = joinErrors(std::move(Errs),
1870 FileCheckErrorDiagnostic::get(
1871 SM, OrigCmdlineName,
1872 "invalid name in string variable definition '" +
1873 OrigCmdlineName + "'"));
1874 continue;
1876 StringRef Name = ParseVarResult->Name;
1878 // Detect collisions between string and numeric variables when the former
1879 // is created later than the latter.
1880 if (GlobalNumericVariableTable.find(Name) !=
1881 GlobalNumericVariableTable.end()) {
1882 Errs = joinErrors(std::move(Errs), FileCheckErrorDiagnostic::get(
1883 SM, Name,
1884 "numeric variable with name '" +
1885 Name + "' already exists"));
1886 continue;
1888 GlobalVariableTable.insert(CmdlineNameVal);
1889 // Mark the string variable as defined to detect collisions between
1890 // string and numeric variables in defineCmdlineVariables when the latter
1891 // is created later than the former. We cannot reuse GlobalVariableTable
1892 // for this by populating it with an empty string since we would then
1893 // lose the ability to detect the use of an undefined variable in
1894 // match().
1895 DefinedVariableTable[Name] = true;
1899 return Errs;
1902 void FileCheckPatternContext::clearLocalVars() {
1903 SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;
1904 for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)
1905 if (Var.first()[0] != '$')
1906 LocalPatternVars.push_back(Var.first());
1908 // Numeric substitution reads the value of a variable directly, not via
1909 // GlobalNumericVariableTable. Therefore, we clear local variables by
1910 // clearing their value which will lead to a numeric substitution failure. We
1911 // also mark the variable for removal from GlobalNumericVariableTable since
1912 // this is what defineCmdlineVariables checks to decide that no global
1913 // variable has been defined.
1914 for (const auto &Var : GlobalNumericVariableTable)
1915 if (Var.first()[0] != '$') {
1916 Var.getValue()->clearValue();
1917 LocalNumericVars.push_back(Var.first());
1920 for (const auto &Var : LocalPatternVars)
1921 GlobalVariableTable.erase(Var);
1922 for (const auto &Var : LocalNumericVars)
1923 GlobalNumericVariableTable.erase(Var);
1926 bool FileCheck::checkInput(SourceMgr &SM, StringRef Buffer,
1927 std::vector<FileCheckDiag> *Diags) {
1928 bool ChecksFailed = false;
1930 unsigned i = 0, j = 0, e = CheckStrings->size();
1931 while (true) {
1932 StringRef CheckRegion;
1933 if (j == e) {
1934 CheckRegion = Buffer;
1935 } else {
1936 const FileCheckString &CheckLabelStr = (*CheckStrings)[j];
1937 if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
1938 ++j;
1939 continue;
1942 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1943 size_t MatchLabelLen = 0;
1944 size_t MatchLabelPos =
1945 CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
1946 if (MatchLabelPos == StringRef::npos)
1947 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
1948 return false;
1950 CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
1951 Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
1952 ++j;
1955 // Do not clear the first region as it's the one before the first
1956 // CHECK-LABEL and it would clear variables defined on the command-line
1957 // before they get used.
1958 if (i != 0 && Req.EnableVarScope)
1959 PatternContext->clearLocalVars();
1961 for (; i != j; ++i) {
1962 const FileCheckString &CheckStr = (*CheckStrings)[i];
1964 // Check each string within the scanned region, including a second check
1965 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1966 size_t MatchLen = 0;
1967 size_t MatchPos =
1968 CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
1970 if (MatchPos == StringRef::npos) {
1971 ChecksFailed = true;
1972 i = j;
1973 break;
1976 CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
1979 if (j == e)
1980 break;
1983 // Success if no checks failed.
1984 return !ChecksFailed;