LLVM 23.0.0git
FileCheck.cpp
Go to the documentation of this file.
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.
11//
12// This file implements most of the API that will be used by the FileCheck utility
13// as well as various unittests.
14//===----------------------------------------------------------------------===//
15
17#include "FileCheckImpl.h"
18#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/StringSet.h"
21#include "llvm/ADT/Twine.h"
23#include <cstdint>
24#include <list>
25#include <set>
26#include <tuple>
27#include <utility>
28
29using namespace llvm;
30
31constexpr static int BackrefLimit = 20;
32
34 switch (Value) {
35 case Kind::NoFormat:
36 return StringRef("<none>");
37 case Kind::Unsigned:
38 return StringRef("%u");
39 case Kind::Signed:
40 return StringRef("%d");
41 case Kind::HexUpper:
42 return StringRef("%X");
43 case Kind::HexLower:
44 return StringRef("%x");
45 }
46 llvm_unreachable("unknown expression format");
47}
48
50 StringRef AlternateFormPrefix = AlternateForm ? StringRef("0x") : StringRef();
51
52 auto CreatePrecisionRegex = [&](StringRef S) {
53 return (Twine(AlternateFormPrefix) + S + Twine('{') + Twine(Precision) +
54 "}")
55 .str();
56 };
57
58 switch (Value) {
59 case Kind::Unsigned:
60 if (Precision)
61 return CreatePrecisionRegex("([1-9][0-9]*)?[0-9]");
62 return std::string("[0-9]+");
63 case Kind::Signed:
64 if (Precision)
65 return CreatePrecisionRegex("-?([1-9][0-9]*)?[0-9]");
66 return std::string("-?[0-9]+");
67 case Kind::HexUpper:
68 if (Precision)
69 return CreatePrecisionRegex("([1-9A-F][0-9A-F]*)?[0-9A-F]");
70 return (Twine(AlternateFormPrefix) + Twine("[0-9A-F]+")).str();
71 case Kind::HexLower:
72 if (Precision)
73 return CreatePrecisionRegex("([1-9a-f][0-9a-f]*)?[0-9a-f]");
74 return (Twine(AlternateFormPrefix) + Twine("[0-9a-f]+")).str();
75 default:
76 return createStringError(std::errc::invalid_argument,
77 "trying to match value with invalid format");
78 }
79}
80
83 if (Value != Kind::Signed && IntValue.isNegative())
85
86 unsigned Radix;
87 bool UpperCase = false;
88 SmallString<8> AbsoluteValueStr;
89 StringRef SignPrefix = IntValue.isNegative() ? "-" : "";
90 switch (Value) {
91 case Kind::Unsigned:
92 case Kind::Signed:
93 Radix = 10;
94 break;
95 case Kind::HexUpper:
96 UpperCase = true;
97 Radix = 16;
98 break;
99 case Kind::HexLower:
100 Radix = 16;
101 UpperCase = false;
102 break;
103 default:
104 return createStringError(std::errc::invalid_argument,
105 "trying to match value with invalid format");
106 }
107 IntValue.abs().toString(AbsoluteValueStr, Radix, /*Signed=*/false,
108 /*formatAsCLiteral=*/false,
109 /*UpperCase=*/UpperCase);
110
111 StringRef AlternateFormPrefix = AlternateForm ? StringRef("0x") : StringRef();
112
113 if (Precision > AbsoluteValueStr.size()) {
114 unsigned LeadingZeros = Precision - AbsoluteValueStr.size();
115 return (Twine(SignPrefix) + Twine(AlternateFormPrefix) +
116 std::string(LeadingZeros, '0') + AbsoluteValueStr)
117 .str();
118 }
119
120 return (Twine(SignPrefix) + Twine(AlternateFormPrefix) + AbsoluteValueStr)
121 .str();
122}
123
124static unsigned nextAPIntBitWidth(unsigned BitWidth) {
126 : BitWidth * 2;
127}
128
129static APInt toSigned(APInt AbsVal, bool Negative) {
130 if (AbsVal.isSignBitSet())
131 AbsVal = AbsVal.zext(nextAPIntBitWidth(AbsVal.getBitWidth()));
132 APInt Result = AbsVal;
133 if (Negative)
134 Result.negate();
135 return Result;
136}
137
139 const SourceMgr &SM) const {
140 bool ValueIsSigned = Value == Kind::Signed;
141 bool Negative = StrVal.consume_front("-");
142 bool Hex = Value == Kind::HexUpper || Value == Kind::HexLower;
143 bool MissingFormPrefix =
144 !ValueIsSigned && AlternateForm && !StrVal.consume_front("0x");
145 (void)MissingFormPrefix;
146 assert(!MissingFormPrefix && "missing alternate form prefix");
147 APInt ResultValue;
148 [[maybe_unused]] bool ParseFailure =
149 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
150 // Both the FileCheck utility and library only call this method with a valid
151 // value in StrVal. This is guaranteed by the regex returned by
152 // getWildcardRegex() above.
153 assert(!ParseFailure && "unable to represent numeric value");
154 return toSigned(ResultValue, Negative);
155}
156
158 const APInt &RightOperand, bool &Overflow) {
159 return LeftOperand.sadd_ov(RightOperand, Overflow);
160}
161
163 const APInt &RightOperand, bool &Overflow) {
164 return LeftOperand.ssub_ov(RightOperand, Overflow);
165}
166
168 const APInt &RightOperand, bool &Overflow) {
169 return LeftOperand.smul_ov(RightOperand, Overflow);
170}
171
173 const APInt &RightOperand, bool &Overflow) {
174 // Check for division by zero.
175 if (RightOperand.isZero())
177
178 return LeftOperand.sdiv_ov(RightOperand, Overflow);
179}
180
182 const APInt &RightOperand, bool &Overflow) {
183 Overflow = false;
184 return LeftOperand.slt(RightOperand) ? RightOperand : LeftOperand;
185}
186
188 const APInt &RightOperand, bool &Overflow) {
189 Overflow = false;
190 if (cantFail(exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
191 return RightOperand;
192
193 return LeftOperand;
194}
195
197 std::optional<APInt> Value = Variable->getValue();
198 if (Value)
199 return *Value;
200
202}
203
205 Expected<APInt> MaybeLeftOp = LeftOperand->eval();
206 Expected<APInt> MaybeRightOp = RightOperand->eval();
207
208 // Bubble up any error (e.g. undefined variables) in the recursive
209 // evaluation.
210 if (!MaybeLeftOp || !MaybeRightOp) {
211 Error Err = Error::success();
212 if (!MaybeLeftOp)
213 Err = joinErrors(std::move(Err), MaybeLeftOp.takeError());
214 if (!MaybeRightOp)
215 Err = joinErrors(std::move(Err), MaybeRightOp.takeError());
216 return std::move(Err);
217 }
218
219 APInt LeftOp = *MaybeLeftOp;
220 APInt RightOp = *MaybeRightOp;
221 bool Overflow;
222 // Ensure both operands have the same bitwidth.
223 unsigned LeftBitWidth = LeftOp.getBitWidth();
224 unsigned RightBitWidth = RightOp.getBitWidth();
225 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
226 LeftOp = LeftOp.sext(NewBitWidth);
227 RightOp = RightOp.sext(NewBitWidth);
228 do {
229 Expected<APInt> MaybeResult = EvalBinop(LeftOp, RightOp, Overflow);
230 if (!MaybeResult)
231 return MaybeResult.takeError();
232
233 if (!Overflow)
234 return MaybeResult;
235
236 NewBitWidth = nextAPIntBitWidth(NewBitWidth);
237 LeftOp = LeftOp.sext(NewBitWidth);
238 RightOp = RightOp.sext(NewBitWidth);
239 } while (true);
240}
241
244 Expected<ExpressionFormat> LeftFormat = LeftOperand->getImplicitFormat(SM);
245 Expected<ExpressionFormat> RightFormat = RightOperand->getImplicitFormat(SM);
246 if (!LeftFormat || !RightFormat) {
247 Error Err = Error::success();
248 if (!LeftFormat)
249 Err = joinErrors(std::move(Err), LeftFormat.takeError());
250 if (!RightFormat)
251 Err = joinErrors(std::move(Err), RightFormat.takeError());
252 return std::move(Err);
253 }
254
255 if (*LeftFormat != ExpressionFormat::Kind::NoFormat &&
256 *RightFormat != ExpressionFormat::Kind::NoFormat &&
257 *LeftFormat != *RightFormat)
260 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
261 "' (" + LeftFormat->toString() + ") and '" +
262 RightOperand->getExpressionStr() + "' (" + RightFormat->toString() +
263 "), need an explicit format specifier");
264
265 return *LeftFormat != ExpressionFormat::Kind::NoFormat ? *LeftFormat
266 : *RightFormat;
267}
268
270 assert(ExpressionPointer->getAST() != nullptr &&
271 "Substituting empty expression");
272 Expected<APInt> EvaluatedValue = ExpressionPointer->getAST()->eval();
273 if (!EvaluatedValue)
274 return EvaluatedValue.takeError();
275 ExpressionFormat Format = ExpressionPointer->getFormat();
276 return Format.getMatchingString(*EvaluatedValue);
277}
278
280 // The "regex" returned by getResultRegex() is just a numeric value
281 // like '42', '0x2A', '-17', 'DEADBEEF' etc. This is already suitable for use
282 // in diagnostics.
284 if (!Literal)
285 return Literal;
286
287 return "\"" + std::move(*Literal) + "\"";
288}
289
291 // Look up the value and escape it so that we can put it into the regex.
292 Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
293 if (!VarVal)
294 return VarVal.takeError();
295 return Regex::escape(*VarVal);
296}
297
299 Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
300 if (!VarVal)
301 return VarVal.takeError();
302
303 std::string Result;
304 Result.reserve(VarVal->size() + 2);
305 raw_string_ostream OS(Result);
306
307 OS << '"';
308 // Escape the string if it contains any characters that
309 // make it hard to read, such as non-printable characters (including all
310 // whitespace except space) and double quotes. These are the characters that
311 // are escaped by write_escaped(), except we do not include backslashes,
312 // because they are common in Windows paths and escaping them would make the
313 // output harder to read. However, when we do escape, backslashes are escaped
314 // as well, otherwise the output would be ambiguous.
315 const bool NeedsEscaping =
316 llvm::any_of(*VarVal, [](char C) { return !isPrint(C) || C == '"'; });
317 if (NeedsEscaping)
318 OS.write_escaped(*VarVal);
319 else
320 OS << *VarVal;
321 OS << '"';
322 if (NeedsEscaping)
323 OS << " (escaped value)";
324
325 return Result;
326}
327
328bool Pattern::isValidVarNameStart(char C) { return C == '_' || isAlpha(C); }
329
332 if (Str.empty())
333 return ErrorDiagnostic::get(SM, Str, "empty variable name");
334
335 size_t I = 0;
336 bool IsPseudo = Str[0] == '@';
337
338 // Global vars start with '$'.
339 if (Str[0] == '$' || IsPseudo)
340 ++I;
341
342 if (I == Str.size())
343 return ErrorDiagnostic::get(SM, Str.substr(I),
344 StringRef("empty ") +
345 (IsPseudo ? "pseudo " : "global ") +
346 "variable name");
347
348 if (!isValidVarNameStart(Str[I++]))
349 return ErrorDiagnostic::get(SM, Str, "invalid variable name");
350
351 for (size_t E = Str.size(); I != E; ++I)
352 // Variable names are composed of alphanumeric characters and underscores.
353 if (Str[I] != '_' && !isAlnum(Str[I]))
354 break;
355
356 StringRef Name = Str.take_front(I);
357 Str = Str.substr(I);
358 return VariableProperties {Name, IsPseudo};
359}
360
361// StringRef holding all characters considered as horizontal whitespaces by
362// FileCheck input canonicalization.
363constexpr StringLiteral SpaceChars = " \t";
364
365// Parsing helper function that strips the first character in S and returns it.
366static char popFront(StringRef &S) {
367 char C = S.front();
368 S = S.drop_front();
369 return C;
370}
371
372char OverflowError::ID = 0;
373char UndefVarError::ID = 0;
374char ErrorDiagnostic::ID = 0;
375char NotFoundError::ID = 0;
376char ErrorReported::ID = 0;
377
378Expected<NumericVariable *> Pattern::parseNumericVariableDefinition(
380 std::optional<size_t> LineNumber, ExpressionFormat ImplicitFormat,
381 const SourceMgr &SM) {
382 Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM);
383 if (!ParseVarResult)
384 return ParseVarResult.takeError();
385 StringRef Name = ParseVarResult->Name;
386
387 if (ParseVarResult->IsPseudo)
389 SM, Name, "definition of pseudo numeric variable unsupported");
390
391 // Detect collisions between string and numeric variables when the latter
392 // is created later than the former.
393 if (Context->DefinedVariableTable.contains(Name))
395 SM, Name, "string variable with name '" + Name + "' already exists");
396
397 Expr = Expr.ltrim(SpaceChars);
398 if (!Expr.empty())
400 SM, Expr, "unexpected characters after numeric variable name");
401
402 NumericVariable *DefinedNumericVariable;
403 auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
404 if (VarTableIter != Context->GlobalNumericVariableTable.end()) {
405 DefinedNumericVariable = VarTableIter->second;
406 if (DefinedNumericVariable->getImplicitFormat() != ImplicitFormat)
408 SM, Expr, "format different from previous variable definition");
409 } else
410 DefinedNumericVariable =
411 Context->makeNumericVariable(Name, ImplicitFormat, LineNumber);
412
413 return DefinedNumericVariable;
414}
415
416Expected<std::unique_ptr<NumericVariableUse>> Pattern::parseNumericVariableUse(
417 StringRef Name, bool IsPseudo, std::optional<size_t> LineNumber,
419 if (IsPseudo && Name != "@LINE")
421 SM, Name, "invalid pseudo numeric variable '" + Name + "'");
422
423 // Numeric variable definitions and uses are parsed in the order in which
424 // they appear in the CHECK patterns. For each definition, the pointer to the
425 // class instance of the corresponding numeric variable definition is stored
426 // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
427 // we get below is null, it means no such variable was defined before. When
428 // that happens, we create a dummy variable so that parsing can continue. All
429 // uses of undefined variables, whether string or numeric, are then diagnosed
430 // in printNoMatch() after failing to match.
431 auto [VarTableIter, Inserted] =
432 Context->GlobalNumericVariableTable.try_emplace(Name);
433 if (Inserted)
434 VarTableIter->second = Context->makeNumericVariable(
435 Name, ExpressionFormat(ExpressionFormat::Kind::Unsigned));
436 NumericVariable *NumericVariable = VarTableIter->second;
437
438 std::optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();
439 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
441 SM, Name,
442 "numeric variable '" + Name +
443 "' defined earlier in the same CHECK directive");
444
445 return std::make_unique<NumericVariableUse>(Name, NumericVariable);
446}
447
448Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericOperand(
449 StringRef &Expr, AllowedOperand AO, bool MaybeInvalidConstraint,
450 std::optional<size_t> LineNumber, FileCheckPatternContext *Context,
451 const SourceMgr &SM) {
452 if (Expr.starts_with("(")) {
453 if (AO != AllowedOperand::Any)
455 SM, Expr, "parenthesized expression not permitted here");
456 return parseParenExpr(Expr, LineNumber, Context, SM);
457 }
458
459 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
460 // Try to parse as a numeric variable use.
461 Expected<Pattern::VariableProperties> ParseVarResult =
462 parseVariable(Expr, SM);
463 if (ParseVarResult) {
464 // Try to parse a function call.
465 if (Expr.ltrim(SpaceChars).starts_with("(")) {
466 if (AO != AllowedOperand::Any)
467 return ErrorDiagnostic::get(SM, ParseVarResult->Name,
468 "unexpected function call");
469
470 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
471 SM);
472 }
473
474 return parseNumericVariableUse(ParseVarResult->Name,
475 ParseVarResult->IsPseudo, LineNumber,
476 Context, SM);
477 }
478
479 if (AO == AllowedOperand::LineVar)
480 return ParseVarResult.takeError();
481 // Ignore the error and retry parsing as a literal.
482 consumeError(ParseVarResult.takeError());
483 }
484
485 // Otherwise, parse it as a literal.
486 APInt LiteralValue;
487 StringRef SaveExpr = Expr;
488 bool Negative = Expr.consume_front("-");
489 if (!Expr.consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
490 LiteralValue)) {
491 LiteralValue = toSigned(LiteralValue, Negative);
492 return std::make_unique<ExpressionLiteral>(SaveExpr.drop_back(Expr.size()),
493 LiteralValue);
494 }
496 SM, SaveExpr,
497 Twine("invalid ") +
498 (MaybeInvalidConstraint ? "matching constraint or " : "") +
499 "operand format");
500}
501
503Pattern::parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber,
505 Expr = Expr.ltrim(SpaceChars);
506 assert(Expr.starts_with("("));
507
508 // Parse right operand.
509 Expr.consume_front("(");
510 Expr = Expr.ltrim(SpaceChars);
511 if (Expr.empty())
512 return ErrorDiagnostic::get(SM, Expr, "missing operand in expression");
513
514 // Note: parseNumericOperand handles nested opening parentheses.
515 Expected<std::unique_ptr<ExpressionAST>> SubExprResult = parseNumericOperand(
516 Expr, AllowedOperand::Any, /*MaybeInvalidConstraint=*/false, LineNumber,
517 Context, SM);
518 Expr = Expr.ltrim(SpaceChars);
519 while (SubExprResult && !Expr.empty() && !Expr.starts_with(")")) {
520 StringRef OrigExpr = Expr;
521 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult), false,
522 LineNumber, Context, SM);
523 Expr = Expr.ltrim(SpaceChars);
524 }
525 if (!SubExprResult)
526 return SubExprResult;
527
528 if (!Expr.consume_front(")")) {
529 return ErrorDiagnostic::get(SM, Expr,
530 "missing ')' at end of nested expression");
531 }
532 return SubExprResult;
533}
534
536Pattern::parseBinop(StringRef Expr, StringRef &RemainingExpr,
537 std::unique_ptr<ExpressionAST> LeftOp,
538 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
540 RemainingExpr = RemainingExpr.ltrim(SpaceChars);
541 if (RemainingExpr.empty())
542 return std::move(LeftOp);
543
544 // Check if this is a supported operation and select a function to perform
545 // it.
546 SMLoc OpLoc = SMLoc::getFromPointer(RemainingExpr.data());
547 char Operator = popFront(RemainingExpr);
548 binop_eval_t EvalBinop;
549 switch (Operator) {
550 case '+':
551 EvalBinop = exprAdd;
552 break;
553 case '-':
554 EvalBinop = exprSub;
555 break;
556 default:
558 SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");
559 }
560
561 // Parse right operand.
562 RemainingExpr = RemainingExpr.ltrim(SpaceChars);
563 if (RemainingExpr.empty())
564 return ErrorDiagnostic::get(SM, RemainingExpr,
565 "missing operand in expression");
566 // The second operand in a legacy @LINE expression is always a literal.
567 AllowedOperand AO =
568 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
569 Expected<std::unique_ptr<ExpressionAST>> RightOpResult =
570 parseNumericOperand(RemainingExpr, AO, /*MaybeInvalidConstraint=*/false,
571 LineNumber, Context, SM);
572 if (!RightOpResult)
573 return RightOpResult;
574
575 Expr = Expr.drop_back(RemainingExpr.size());
576 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
577 std::move(*RightOpResult));
578}
579
581Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName,
582 std::optional<size_t> LineNumber,
584 Expr = Expr.ltrim(SpaceChars);
585 assert(Expr.starts_with("("));
586
587 auto OptFunc = StringSwitch<binop_eval_t>(FuncName)
588 .Case("add", exprAdd)
589 .Case("div", exprDiv)
590 .Case("max", exprMax)
591 .Case("min", exprMin)
592 .Case("mul", exprMul)
593 .Case("sub", exprSub)
594 .Default(nullptr);
595
596 if (!OptFunc)
598 SM, FuncName, Twine("call to undefined function '") + FuncName + "'");
599
600 Expr.consume_front("(");
601 Expr = Expr.ltrim(SpaceChars);
602
603 // Parse call arguments, which are comma separated.
605 while (!Expr.empty() && !Expr.starts_with(")")) {
606 if (Expr.starts_with(","))
607 return ErrorDiagnostic::get(SM, Expr, "missing argument");
608
609 // Parse the argument, which is an arbitary expression.
610 StringRef OuterBinOpExpr = Expr;
611 Expected<std::unique_ptr<ExpressionAST>> Arg = parseNumericOperand(
612 Expr, AllowedOperand::Any, /*MaybeInvalidConstraint=*/false, LineNumber,
613 Context, SM);
614 while (Arg && !Expr.empty()) {
615 Expr = Expr.ltrim(SpaceChars);
616 // Have we reached an argument terminator?
617 if (Expr.starts_with(",") || Expr.starts_with(")"))
618 break;
619
620 // Arg = Arg <op> <expr>
621 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg), false, LineNumber,
622 Context, SM);
623 }
624
625 // Prefer an expression error over a generic invalid argument message.
626 if (!Arg)
627 return Arg.takeError();
628 Args.push_back(std::move(*Arg));
629
630 // Have we parsed all available arguments?
631 Expr = Expr.ltrim(SpaceChars);
632 if (!Expr.consume_front(","))
633 break;
634
635 Expr = Expr.ltrim(SpaceChars);
636 if (Expr.starts_with(")"))
637 return ErrorDiagnostic::get(SM, Expr, "missing argument");
638 }
639
640 if (!Expr.consume_front(")"))
641 return ErrorDiagnostic::get(SM, Expr,
642 "missing ')' at end of call expression");
643
644 const unsigned NumArgs = Args.size();
645 if (NumArgs == 2)
646 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
647 std::move(Args[1]));
648
649 // TODO: Support more than binop_eval_t.
650 return ErrorDiagnostic::get(SM, FuncName,
651 Twine("function '") + FuncName +
652 Twine("' takes 2 arguments but ") +
653 Twine(NumArgs) + " given");
654}
655
657 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
658 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
659 FileCheckPatternContext *Context, const SourceMgr &SM) {
660 std::unique_ptr<ExpressionAST> ExpressionASTPointer = nullptr;
661 StringRef DefExpr = StringRef();
662 DefinedNumericVariable = std::nullopt;
663 ExpressionFormat ExplicitFormat = ExpressionFormat();
664 unsigned Precision = 0;
665
666 // Parse format specifier (NOTE: ',' is also an argument separator).
667 size_t FormatSpecEnd = Expr.find(',');
668 size_t FunctionStart = Expr.find('(');
669 if (FormatSpecEnd != StringRef::npos && FormatSpecEnd < FunctionStart) {
670 StringRef FormatExpr = Expr.take_front(FormatSpecEnd);
671 Expr = Expr.drop_front(FormatSpecEnd + 1);
672 FormatExpr = FormatExpr.trim(SpaceChars);
673 if (!FormatExpr.consume_front("%"))
675 SM, FormatExpr,
676 "invalid matching format specification in expression");
677
678 // Parse alternate form flag.
679 SMLoc AlternateFormFlagLoc = SMLoc::getFromPointer(FormatExpr.data());
680 bool AlternateForm = FormatExpr.consume_front("#");
681
682 // Parse precision.
683 if (FormatExpr.consume_front(".")) {
684 if (FormatExpr.consumeInteger(10, Precision))
685 return ErrorDiagnostic::get(SM, FormatExpr,
686 "invalid precision in format specifier");
687 }
688
689 if (!FormatExpr.empty()) {
690 // Check for unknown matching format specifier and set matching format in
691 // class instance representing this expression.
692 SMLoc FmtLoc = SMLoc::getFromPointer(FormatExpr.data());
693 switch (popFront(FormatExpr)) {
694 case 'u':
695 ExplicitFormat =
697 break;
698 case 'd':
699 ExplicitFormat =
701 break;
702 case 'x':
704 Precision, AlternateForm);
705 break;
706 case 'X':
708 Precision, AlternateForm);
709 break;
710 default:
711 return ErrorDiagnostic::get(SM, FmtLoc,
712 "invalid format specifier in expression");
713 }
714 }
715
716 if (AlternateForm && ExplicitFormat != ExpressionFormat::Kind::HexLower &&
717 ExplicitFormat != ExpressionFormat::Kind::HexUpper)
719 SM, AlternateFormFlagLoc,
720 "alternate form only supported for hex values");
721
722 FormatExpr = FormatExpr.ltrim(SpaceChars);
723 if (!FormatExpr.empty())
725 SM, FormatExpr,
726 "invalid matching format specification in expression");
727 }
728
729 // Save variable definition expression if any.
730 size_t DefEnd = Expr.find(':');
731 if (DefEnd != StringRef::npos) {
732 DefExpr = Expr.substr(0, DefEnd);
733 Expr = Expr.substr(DefEnd + 1);
734 }
735
736 // Parse matching constraint.
737 Expr = Expr.ltrim(SpaceChars);
738 bool HasParsedValidConstraint = Expr.consume_front("==");
739
740 // Parse the expression itself.
741 Expr = Expr.ltrim(SpaceChars);
742 if (Expr.empty()) {
743 if (HasParsedValidConstraint)
745 SM, Expr, "empty numeric expression should not have a constraint");
746 } else {
747 Expr = Expr.rtrim(SpaceChars);
748 StringRef OuterBinOpExpr = Expr;
749 // The first operand in a legacy @LINE expression is always the @LINE
750 // pseudo variable.
751 AllowedOperand AO =
752 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
754 Expr, AO, !HasParsedValidConstraint, LineNumber, Context, SM);
755 while (ParseResult && !Expr.empty()) {
756 ParseResult = parseBinop(OuterBinOpExpr, Expr, std::move(*ParseResult),
757 IsLegacyLineExpr, LineNumber, Context, SM);
758 // Legacy @LINE expressions only allow 2 operands.
759 if (ParseResult && IsLegacyLineExpr && !Expr.empty())
761 SM, Expr,
762 "unexpected characters at end of expression '" + Expr + "'");
763 }
764 if (!ParseResult)
765 return ParseResult.takeError();
766 ExpressionASTPointer = std::move(*ParseResult);
767 }
768
769 // Select format of the expression, i.e. (i) its explicit format, if any,
770 // otherwise (ii) its implicit format, if any, otherwise (iii) the default
771 // format (unsigned). Error out in case of conflicting implicit format
772 // without explicit format.
774 if (ExplicitFormat)
775 Format = ExplicitFormat;
776 else if (ExpressionASTPointer) {
777 Expected<ExpressionFormat> ImplicitFormat =
778 ExpressionASTPointer->getImplicitFormat(SM);
779 if (!ImplicitFormat)
780 return ImplicitFormat.takeError();
781 Format = *ImplicitFormat;
782 }
783 if (!Format)
785
786 std::unique_ptr<Expression> ExpressionPointer =
787 std::make_unique<Expression>(std::move(ExpressionASTPointer), Format);
788
789 // Parse the numeric variable definition.
790 if (DefEnd != StringRef::npos) {
791 DefExpr = DefExpr.ltrim(SpaceChars);
792 Expected<NumericVariable *> ParseResult = parseNumericVariableDefinition(
793 DefExpr, Context, LineNumber, ExpressionPointer->getFormat(), SM);
794
795 if (!ParseResult)
796 return ParseResult.takeError();
797 DefinedNumericVariable = *ParseResult;
798 }
799
800 return std::move(ExpressionPointer);
801}
802
804 SourceMgr &SM, const FileCheckRequest &Req) {
805 bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
806 IgnoreCase = Req.IgnoreCase;
807
808 PatternLoc = SMLoc::getFromPointer(PatternStr.data());
809
811 // Ignore trailing whitespace.
812 PatternStr = PatternStr.rtrim(" \t");
813
814 // Check that there is something on the line.
815 if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
816 SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
817 "found empty check string with prefix '" + Prefix + ":'");
818 return true;
819 }
820
821 if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
822 SM.PrintMessage(
823 PatternLoc, SourceMgr::DK_Error,
824 "found non-empty check string for empty check with prefix '" + Prefix +
825 ":'");
826 return true;
827 }
828
829 if (CheckTy == Check::CheckEmpty) {
830 RegExStr = "(\n$)";
831 return false;
832 }
833
834 // If literal check, set fixed string.
835 if (CheckTy.isLiteralMatch()) {
836 FixedStr = PatternStr;
837 return false;
838 }
839
840 // Check to see if this is a fixed string, or if it has regex pieces.
841 if (!MatchFullLinesHere &&
842 (PatternStr.size() < 2 ||
843 (!PatternStr.contains("{{") && !PatternStr.contains("[[")))) {
844 FixedStr = PatternStr;
845 return false;
846 }
847
848 if (MatchFullLinesHere) {
849 RegExStr += '^';
851 RegExStr += " *";
852 }
853
854 // Paren value #0 is for the fully matched string. Any new parenthesized
855 // values add from there.
856 unsigned CurParen = 1;
857
858 // Otherwise, there is at least one regex piece. Build up the regex pattern
859 // by escaping scary characters in fixed strings, building up one big regex.
860 while (!PatternStr.empty()) {
861 // RegEx matches.
862 if (PatternStr.starts_with("{{")) {
863 // This is the start of a regex match. Scan for the }}.
864 size_t End = PatternStr.find("}}");
865 if (End == StringRef::npos) {
866 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
868 "found start of regex string with no end '}}'");
869 return true;
870 }
871
872 // Enclose {{}} patterns in parens just like [[]] even though we're not
873 // capturing the result for any purpose. This is required in case the
874 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
875 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
876 bool HasAlternation = PatternStr.contains('|');
877 if (HasAlternation) {
878 RegExStr += '(';
879 ++CurParen;
880 }
881
882 if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
883 return true;
884 if (HasAlternation)
885 RegExStr += ')';
886
887 PatternStr = PatternStr.substr(End + 2);
888 continue;
889 }
890
891 // String and numeric substitution blocks. Pattern substitution blocks come
892 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
893 // other regex) and assigns it to the string variable 'foo'. The latter
894 // substitutes foo's value. Numeric substitution blocks recognize the same
895 // form as string ones, but start with a '#' sign after the double
896 // brackets. They also accept a combined form which sets a numeric variable
897 // to the evaluation of an expression. Both string and numeric variable
898 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
899 // valid, as this helps catch some common errors. If there are extra '['s
900 // before the "[[", treat them literally.
901 if (PatternStr.starts_with("[[") && !PatternStr.starts_with("[[[")) {
902 StringRef UnparsedPatternStr = PatternStr.substr(2);
903 // Find the closing bracket pair ending the match. End is going to be an
904 // offset relative to the beginning of the match string.
905 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
906 StringRef MatchStr = UnparsedPatternStr.substr(0, End);
907 bool IsNumBlock = MatchStr.consume_front("#");
908
909 if (End == StringRef::npos) {
910 SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
912 "Invalid substitution block, no ]] found");
913 return true;
914 }
915 // Strip the substitution block we are parsing. End points to the start
916 // of the "]]" closing the expression so account for it in computing the
917 // index of the first unparsed character.
918 PatternStr = UnparsedPatternStr.substr(End + 2);
919
920 bool IsDefinition = false;
921 bool SubstNeeded = false;
922 // Whether the substitution block is a legacy use of @LINE with string
923 // substitution block syntax.
924 bool IsLegacyLineExpr = false;
925 StringRef DefName;
926 StringRef SubstStr;
927 StringRef MatchRegexp;
928 std::string WildcardRegexp;
929 size_t SubstInsertIdx = RegExStr.size();
930
931 // Parse string variable or legacy @LINE expression.
932 if (!IsNumBlock) {
933 size_t VarEndIdx = MatchStr.find(':');
934 size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
935 if (SpacePos != StringRef::npos) {
936 SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos),
937 SourceMgr::DK_Error, "unexpected whitespace");
938 return true;
939 }
940
941 // Get the name (e.g. "foo") and verify it is well formed.
942 StringRef OrigMatchStr = MatchStr;
944 parseVariable(MatchStr, SM);
945 if (!ParseVarResult) {
946 logAllUnhandledErrors(ParseVarResult.takeError(), errs());
947 return true;
948 }
949 StringRef Name = ParseVarResult->Name;
950 bool IsPseudo = ParseVarResult->IsPseudo;
951
952 IsDefinition = (VarEndIdx != StringRef::npos);
953 SubstNeeded = !IsDefinition;
954 if (IsDefinition) {
955 if ((IsPseudo || !MatchStr.consume_front(":"))) {
956 SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
958 "invalid name in string variable definition");
959 return true;
960 }
961
962 // Detect collisions between string and numeric variables when the
963 // former is created later than the latter.
964 if (Context->GlobalNumericVariableTable.contains(Name)) {
965 SM.PrintMessage(
967 "numeric variable with name '" + Name + "' already exists");
968 return true;
969 }
970 DefName = Name;
971 MatchRegexp = MatchStr;
972 } else {
973 if (IsPseudo) {
974 MatchStr = OrigMatchStr;
975 IsLegacyLineExpr = IsNumBlock = true;
976 } else {
977 if (!MatchStr.empty()) {
978 SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
980 "invalid name in string variable use");
981 return true;
982 }
983 SubstStr = Name;
984 }
985 }
986 }
987
988 // Parse numeric substitution block.
989 std::unique_ptr<Expression> ExpressionPointer;
990 std::optional<NumericVariable *> DefinedNumericVariable;
991 if (IsNumBlock) {
993 parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable,
994 IsLegacyLineExpr, LineNumber, Context,
995 SM);
996 if (!ParseResult) {
997 logAllUnhandledErrors(ParseResult.takeError(), errs());
998 return true;
999 }
1000 ExpressionPointer = std::move(*ParseResult);
1001 SubstNeeded = ExpressionPointer->getAST() != nullptr;
1002 if (DefinedNumericVariable) {
1003 IsDefinition = true;
1004 DefName = (*DefinedNumericVariable)->getName();
1005 }
1006 if (SubstNeeded)
1007 SubstStr = MatchStr;
1008 else {
1009 ExpressionFormat Format = ExpressionPointer->getFormat();
1010 WildcardRegexp = cantFail(Format.getWildcardRegex());
1011 MatchRegexp = WildcardRegexp;
1012 }
1013 }
1014
1015 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
1016 if (IsDefinition) {
1017 RegExStr += '(';
1018 ++SubstInsertIdx;
1019
1020 if (IsNumBlock) {
1021 NumericVariableMatch NumericVariableDefinition = {
1022 *DefinedNumericVariable, CurParen};
1023 NumericVariableDefs[DefName] = NumericVariableDefinition;
1024 // This store is done here rather than in match() to allow
1025 // parseNumericVariableUse() to get the pointer to the class instance
1026 // of the right variable definition corresponding to a given numeric
1027 // variable use.
1028 Context->GlobalNumericVariableTable[DefName] =
1029 *DefinedNumericVariable;
1030 } else {
1031 VariableDefs[DefName] = CurParen;
1032 // Mark string variable as defined to detect collisions between
1033 // string and numeric variables in parseNumericVariableUse() and
1034 // defineCmdlineVariables() when the latter is created later than the
1035 // former. We cannot reuse GlobalVariableTable for this by populating
1036 // it with an empty string since we would then lose the ability to
1037 // detect the use of an undefined variable in match().
1038 Context->DefinedVariableTable[DefName] = true;
1039 }
1040
1041 ++CurParen;
1042 }
1043
1044 if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1045 return true;
1046
1047 if (IsDefinition)
1048 RegExStr += ')';
1049
1050 // Handle substitutions: [[foo]] and [[#<foo expr>]].
1051 if (SubstNeeded) {
1052 // Handle substitution of string variables that were defined earlier on
1053 // the same line by emitting a backreference. Expressions do not
1054 // support substituting a numeric variable defined on the same line.
1055 decltype(VariableDefs)::iterator It;
1056 if (!IsNumBlock &&
1057 (It = VariableDefs.find(SubstStr)) != VariableDefs.end()) {
1058 unsigned CaptureParenGroup = It->second;
1059 if (CaptureParenGroup < 1 || CaptureParenGroup > BackrefLimit) {
1060 SM.PrintMessage(SMLoc::getFromPointer(SubstStr.data()),
1062 "Can't back-reference more than " +
1063 Twine(BackrefLimit) + " variables");
1064 return true;
1065 }
1066 AddBackrefToRegEx(CaptureParenGroup);
1067 } else {
1068 // Handle substitution of string variables ([[<var>]]) defined in
1069 // previous CHECK patterns, and substitution of expressions.
1071 IsNumBlock
1072 ? Context->makeNumericSubstitution(
1073 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1074 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1075 Substitutions.push_back(Substitution);
1076 }
1077 }
1078
1079 continue;
1080 }
1081
1082 // Handle fixed string matches.
1083 // Find the end, which is the start of the next regex.
1084 size_t FixedMatchEnd =
1085 std::min(PatternStr.find("{{", 1), PatternStr.find("[[", 1));
1086 RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
1087 PatternStr = PatternStr.substr(FixedMatchEnd);
1088 }
1089
1090 if (MatchFullLinesHere) {
1091 if (!Req.NoCanonicalizeWhiteSpace)
1092 RegExStr += " *";
1093 RegExStr += '$';
1094 }
1095
1096 return false;
1097}
1098
1099bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
1100 Regex R(RS);
1101 std::string Error;
1102 if (!R.isValid(Error)) {
1103 SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
1104 "invalid regex: " + Error);
1105 return true;
1106 }
1107
1108 RegExStr += RS.str();
1109 CurParen += R.getNumMatches();
1110 return false;
1111}
1112
1113void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
1114 assert(BackrefNum >= 1 && BackrefNum <= BackrefLimit &&
1115 "Invalid backref number");
1116 std::string Backref;
1117 if (BackrefNum >= 1 && BackrefNum <= 9)
1118 Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
1119 else
1120 Backref = std::string("\\g{") + std::to_string(BackrefNum) + '}';
1121
1122 RegExStr += Backref;
1123}
1124
1126 const SourceMgr &SM) const {
1127 // If this is the EOF pattern, match it immediately.
1128 if (CheckTy == Check::CheckEOF)
1129 return MatchResult(Buffer.size(), 0, Error::success());
1130
1131 // If this is a fixed string pattern, just match it now.
1132 if (!FixedStr.empty()) {
1133 size_t Pos =
1134 IgnoreCase ? Buffer.find_insensitive(FixedStr) : Buffer.find(FixedStr);
1135 if (Pos == StringRef::npos)
1137 return MatchResult(Pos, /*MatchLen=*/FixedStr.size(), Error::success());
1138 }
1139
1140 // Regex match.
1141
1142 // If there are substitutions, we need to create a temporary string with the
1143 // actual value.
1144 StringRef RegExToMatch = RegExStr;
1145 std::string TmpStr;
1146 if (!Substitutions.empty()) {
1147 TmpStr = RegExStr;
1148 if (LineNumber)
1149 Context->LineVariable->setValue(
1150 APInt(sizeof(*LineNumber) * 8, *LineNumber));
1151
1152 size_t InsertOffset = 0;
1153 // Substitute all string variables and expressions whose values are only
1154 // now known. Use of string variables defined on the same line are handled
1155 // by back-references.
1156 Error Errs = Error::success();
1157 for (const auto &Substitution : Substitutions) {
1158 // Substitute and check for failure (e.g. use of undefined variable).
1160 if (!Value) {
1161 // Convert to an ErrorDiagnostic to get location information. This is
1162 // done here rather than printMatch/printNoMatch since now we know which
1163 // substitution block caused the overflow.
1164 Errs = joinErrors(std::move(Errs),
1166 Value.takeError(),
1167 [&](const OverflowError &E) {
1168 return ErrorDiagnostic::get(
1169 SM, Substitution->getFromString(),
1170 "unable to substitute variable or "
1171 "numeric expression: overflow error");
1172 },
1173 [&SM](const UndefVarError &E) {
1174 return ErrorDiagnostic::get(SM, E.getVarName(),
1175 E.message());
1176 }));
1177 continue;
1178 }
1179
1180 // Plop it into the regex at the adjusted offset.
1181 TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset,
1182 Value->begin(), Value->end());
1183 InsertOffset += Value->size();
1184 }
1185 if (Errs)
1186 return std::move(Errs);
1187
1188 // Match the newly constructed regex.
1189 RegExToMatch = TmpStr;
1190 }
1191
1192 SmallVector<StringRef, 4> MatchInfo;
1193 unsigned int Flags = Regex::Newline;
1194 if (IgnoreCase)
1195 Flags |= Regex::IgnoreCase;
1196 if (!Regex(RegExToMatch, Flags).match(Buffer, &MatchInfo))
1198
1199 // Successful regex match.
1200 assert(!MatchInfo.empty() && "Didn't get any match");
1201 StringRef FullMatch = MatchInfo[0];
1202
1203 // If this defines any string variables, remember their values.
1204 for (const auto &VariableDef : VariableDefs) {
1205 assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
1206 Context->GlobalVariableTable[VariableDef.first] =
1207 MatchInfo[VariableDef.second];
1208 }
1209
1210 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
1211 // the required preceding newline, which is consumed by the pattern in the
1212 // case of CHECK-EMPTY but not CHECK-NEXT.
1213 size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
1214 Match TheMatch;
1215 TheMatch.Pos = FullMatch.data() - Buffer.data() + MatchStartSkip;
1216 TheMatch.Len = FullMatch.size() - MatchStartSkip;
1217
1218 // If this defines any numeric variables, remember their values.
1219 for (const auto &NumericVariableDef : NumericVariableDefs) {
1220 const NumericVariableMatch &NumericVariableMatch =
1221 NumericVariableDef.getValue();
1222 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1223 assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");
1224 NumericVariable *DefinedNumericVariable =
1225 NumericVariableMatch.DefinedNumericVariable;
1226
1227 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1228 ExpressionFormat Format = DefinedNumericVariable->getImplicitFormat();
1229 APInt Value = Format.valueFromStringRepr(MatchedValue, SM);
1230 // Numeric variables are already inserted into GlobalNumericVariableTable
1231 // during parsing, but clearLocalVars might remove them, so we must
1232 // reinsert them. Numeric-variable resolution does not access
1233 // GlobalNumericVariableTable; it directly uses a pointer to the variable.
1234 // However, other functions (such as clearLocalVars) may require active
1235 // variables to be in the table.
1236 Context->GlobalNumericVariableTable.try_emplace(NumericVariableDef.getKey(),
1237 DefinedNumericVariable);
1238 DefinedNumericVariable->setValue(Value, MatchedValue);
1239 }
1240
1241 return MatchResult(TheMatch, Error::success());
1242}
1243
1244unsigned Pattern::computeMatchDistance(StringRef Buffer) const {
1245 // Just compute the number of matching characters. For regular expressions, we
1246 // just compare against the regex itself and hope for the best.
1247 //
1248 // FIXME: One easy improvement here is have the regex lib generate a single
1249 // example regular expression which matches, and use that as the example
1250 // string.
1251 StringRef ExampleString(FixedStr);
1252 if (ExampleString.empty())
1253 ExampleString = RegExStr;
1254
1255 // Only compare up to the first line in the buffer, or the string size.
1256 StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
1257 BufferPrefix = BufferPrefix.split('\n').first;
1258 return BufferPrefix.edit_distance(ExampleString);
1259}
1260
1262 SMRange Range,
1263 FileCheckDiagList *Diags) const {
1264 // Print what we know about substitutions.
1265 if (!Substitutions.empty()) {
1266 for (const auto &Substitution : Substitutions) {
1267 SmallString<256> Msg;
1268 raw_svector_ostream OS(Msg);
1269
1270 Expected<std::string> MatchedValue =
1272 // Substitution failures are handled in printNoMatch().
1273 if (!MatchedValue) {
1274 consumeError(MatchedValue.takeError());
1275 continue;
1276 }
1277
1278 OS << "with \"";
1279 OS.write_escaped(Substitution->getFromString()) << "\" equal to ";
1280 OS << *MatchedValue;
1281
1282 // Unlike MatchCustomNoteDiag, PrintMessage needs a location. We report
1283 // only the start of the match/search range to suggest we are reporting
1284 // the substitutions as set at the start of the match/search. Indicating
1285 // a non-zero-length range might instead seem to imply that the
1286 // substitution matches or was captured from exactly that range.
1287 if (Diags)
1288 Diags->emplace<MatchCustomNoteDiag>(OS.str());
1289 else
1290 SM.PrintMessage(Range.Start, SourceMgr::DK_Note, OS.str());
1291 }
1292 }
1293}
1294
1296 FileCheckDiagList *Diags) const {
1297 if (VariableDefs.empty() && NumericVariableDefs.empty())
1298 return;
1299 // Build list of variable captures.
1300 struct VarCapture {
1301 StringRef Name;
1302 SMRange Range;
1303 };
1304 SmallVector<VarCapture, 2> VarCaptures;
1305 for (const auto &VariableDef : VariableDefs) {
1306 VarCapture VC;
1307 VC.Name = VariableDef.first;
1308 StringRef Value = Context->GlobalVariableTable[VC.Name];
1309 SMLoc Start = SMLoc::getFromPointer(Value.data());
1310 SMLoc End = SMLoc::getFromPointer(Value.data() + Value.size());
1311 VC.Range = SMRange(Start, End);
1312 VarCaptures.push_back(VC);
1313 }
1314 for (const auto &VariableDef : NumericVariableDefs) {
1315 VarCapture VC;
1316 VC.Name = VariableDef.getKey();
1317 std::optional<StringRef> StrValue =
1318 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1319 if (!StrValue)
1320 continue;
1321 SMLoc Start = SMLoc::getFromPointer(StrValue->data());
1322 SMLoc End = SMLoc::getFromPointer(StrValue->data() + StrValue->size());
1323 VC.Range = SMRange(Start, End);
1324 VarCaptures.push_back(VC);
1325 }
1326 // Sort variable captures by the order in which they matched the input.
1327 // Ranges shouldn't be overlapping, so we can just compare the start.
1328 llvm::sort(VarCaptures, [](const VarCapture &A, const VarCapture &B) {
1329 if (&A == &B)
1330 return false;
1331 assert(A.Range.Start != B.Range.Start &&
1332 "unexpected overlapping variable captures");
1333 return A.Range.Start.getPointer() < B.Range.Start.getPointer();
1334 });
1335 // Create notes for the sorted captures.
1336 for (const VarCapture &VC : VarCaptures) {
1337 SmallString<256> Msg;
1338 raw_svector_ostream OS(Msg);
1339 OS << "captured var \"" << VC.Name << "\"";
1340 if (Diags)
1341 Diags->emplace<MatchCustomNoteDiag>(VC.Range, OS.str());
1342 else
1343 SM.PrintMessage(VC.Range.Start, SourceMgr::DK_Note, OS.str(), VC.Range);
1344 }
1345}
1346
1347static SMRange buildMatchRange(StringRef Buffer, size_t Pos, size_t Len) {
1348 return SMRange(SMLoc::getFromPointer(Buffer.data() + Pos),
1349 SMLoc::getFromPointer(Buffer.data() + Pos + Len));
1350}
1351
1353 return SMRange(SMLoc::getFromPointer(Buffer.data()),
1354 SMLoc::getFromPointer(Buffer.data() + Buffer.size()));
1355}
1356
1358 FileCheckDiagList *Diags) const {
1359 // Attempt to find the closest/best fuzzy match. Usually an error happens
1360 // because some string in the output didn't exactly match. In these cases, we
1361 // would like to show the user a best guess at what "should have" matched, to
1362 // save them having to actually check the input manually.
1363 size_t NumLinesForward = 0;
1364 size_t Best = StringRef::npos;
1365 double BestQuality = 0;
1366
1367 // Arbitrarily limit quadratic search behavior stemming from long CHECK lines.
1368 if (size_t(4096) * size_t(2048) <
1369 std::min(size_t(4096), Buffer.size()) *
1370 std::max(FixedStr.size(), RegExStr.size()))
1371 return;
1372
1373 // Use an arbitrary 4k limit on how far we will search.
1374 for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
1375 if (Buffer[i] == '\n')
1376 ++NumLinesForward;
1377
1378 // Patterns have leading whitespace stripped, so skip whitespace when
1379 // looking for something which looks like a pattern.
1380 if (Buffer[i] == ' ' || Buffer[i] == '\t')
1381 continue;
1382
1383 // Compute the "quality" of this match as an arbitrary combination of the
1384 // match distance and the number of lines skipped to get to this match.
1385 unsigned Distance = computeMatchDistance(Buffer.substr(i));
1386 double Quality = Distance + (NumLinesForward / 100.);
1387
1388 if (Quality < BestQuality || Best == StringRef::npos) {
1389 Best = i;
1390 BestQuality = Quality;
1391 }
1392 }
1393
1394 // Print the "possible intended match here" line if we found something
1395 // reasonable and not equal to what we showed in the "scanning from here"
1396 // line.
1397 if (Best && Best != StringRef::npos && BestQuality < 50) {
1398 SMLoc MatchStart = SMLoc::getFromPointer(Buffer.data() + Best);
1399 if (Diags)
1400 Diags->emplace<MatchFuzzyDiag>(MatchStart);
1401 SM.PrintMessage(MatchStart, SourceMgr::DK_Note,
1402 "possible intended match here");
1403
1404 // FIXME: If we wanted to be really friendly we would show why the match
1405 // failed, as it can be hard to spot simple one character differences.
1406 }
1407}
1408
1411 auto VarIter = GlobalVariableTable.find(VarName);
1412 if (VarIter == GlobalVariableTable.end())
1413 return make_error<UndefVarError>(VarName);
1414
1415 return VarIter->second;
1416}
1417
1418template <class... Types>
1419NumericVariable *FileCheckPatternContext::makeNumericVariable(Types... args) {
1420 NumericVariables.push_back(std::make_unique<NumericVariable>(args...));
1421 return NumericVariables.back().get();
1422}
1423
1425FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
1426 size_t InsertIdx) {
1427 Substitutions.push_back(
1428 std::make_unique<StringSubstitution>(this, VarName, InsertIdx));
1429 return Substitutions.back().get();
1430}
1431
1432Substitution *FileCheckPatternContext::makeNumericSubstitution(
1433 StringRef ExpressionStr, std::unique_ptr<Expression> Expression,
1434 size_t InsertIdx) {
1435 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1436 this, ExpressionStr, std::move(Expression), InsertIdx));
1437 return Substitutions.back().get();
1438}
1439
1440size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
1441 // Offset keeps track of the current offset within the input Str
1442 size_t Offset = 0;
1443 // [...] Nesting depth
1444 size_t BracketDepth = 0;
1445
1446 while (!Str.empty()) {
1447 if (Str.starts_with("]]") && BracketDepth == 0)
1448 return Offset;
1449 if (Str[0] == '\\') {
1450 // Backslash escapes the next char within regexes, so skip them both.
1451 Str = Str.substr(2);
1452 Offset += 2;
1453 } else {
1454 switch (Str[0]) {
1455 default:
1456 break;
1457 case '[':
1458 BracketDepth++;
1459 break;
1460 case ']':
1461 if (BracketDepth == 0) {
1462 SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
1464 "missing closing \"]\" for regex variable");
1465 exit(1);
1466 }
1467 BracketDepth--;
1468 break;
1469 }
1470 Str = Str.substr(1);
1471 Offset++;
1472 }
1473 }
1474
1475 return StringRef::npos;
1476}
1477
1480 OutputBuffer.reserve(MB.getBufferSize());
1481
1482 for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
1483 Ptr != End; ++Ptr) {
1484 // Eliminate trailing dosish \r.
1485 if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
1486 continue;
1487 }
1488
1489 // If current char is not a horizontal whitespace or if horizontal
1490 // whitespace canonicalization is disabled, dump it to output as is.
1491 if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
1492 OutputBuffer.push_back(*Ptr);
1493 continue;
1494 }
1495
1496 // Otherwise, add one space and advance over neighboring space.
1497 OutputBuffer.push_back(' ');
1498 while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
1499 ++Ptr;
1500 }
1501
1502 // Add a null byte and then return all but that byte.
1503 OutputBuffer.push_back('\0');
1504 return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
1505}
1506
1510
1511static bool IsPartOfWord(char c) {
1512 return (isAlnum(c) || c == '-' || c == '_');
1513}
1514
1516 assert(Count > 0 && "zero and negative counts are not supported");
1517 assert((C == 1 || Kind == CheckPlain) &&
1518 "count supported only for plain CHECK directives");
1519 Count = C;
1520 return *this;
1521}
1522
1524 if (Modifiers.none())
1525 return "";
1526 std::string Ret;
1527 raw_string_ostream OS(Ret);
1528 OS << '{';
1529 if (isLiteralMatch())
1530 OS << "LITERAL";
1531 OS << '}';
1532 return Ret;
1533}
1534
1536 // Append directive modifiers.
1537 auto WithModifiers = [this, Prefix](StringRef Str) -> std::string {
1538 return (Prefix + Str + getModifiersDescription()).str();
1539 };
1540
1541 switch (Kind) {
1542 case Check::CheckNone:
1543 return "invalid";
1545 return "misspelled";
1546 case Check::CheckPlain:
1547 if (Count > 1)
1548 return WithModifiers("-COUNT");
1549 return WithModifiers("");
1550 case Check::CheckNext:
1551 return WithModifiers("-NEXT");
1552 case Check::CheckSame:
1553 return WithModifiers("-SAME");
1554 case Check::CheckNot:
1555 return WithModifiers("-NOT");
1556 case Check::CheckDAG:
1557 return WithModifiers("-DAG");
1558 case Check::CheckLabel:
1559 return WithModifiers("-LABEL");
1560 case Check::CheckEmpty:
1561 return WithModifiers("-EMPTY");
1563 return std::string(Prefix);
1564 case Check::CheckEOF:
1565 return "implicit EOF";
1566 case Check::CheckBadNot:
1567 return "bad NOT";
1569 return "bad COUNT";
1570 }
1571 llvm_unreachable("unknown FileCheckType");
1572}
1573
1574static std::pair<Check::FileCheckType, StringRef>
1576 bool &Misspelled) {
1577 if (Buffer.size() <= Prefix.size())
1578 return {Check::CheckNone, StringRef()};
1579
1580 StringRef Rest = Buffer.drop_front(Prefix.size());
1581 // Check for comment.
1582 if (llvm::is_contained(Req.CommentPrefixes, Prefix)) {
1583 if (Rest.consume_front(":"))
1584 return {Check::CheckComment, Rest};
1585 // Ignore a comment prefix if it has a suffix like "-NOT".
1586 return {Check::CheckNone, StringRef()};
1587 }
1588
1589 auto ConsumeModifiers = [&](Check::FileCheckType Ret)
1590 -> std::pair<Check::FileCheckType, StringRef> {
1591 if (Rest.consume_front(":"))
1592 return {Ret, Rest};
1593 if (!Rest.consume_front("{"))
1594 return {Check::CheckNone, StringRef()};
1595
1596 // Parse the modifiers, speparated by commas.
1597 do {
1598 // Allow whitespace in modifiers list.
1599 Rest = Rest.ltrim();
1600 if (Rest.consume_front("LITERAL"))
1601 Ret.setLiteralMatch();
1602 else
1603 return {Check::CheckNone, Rest};
1604 // Allow whitespace in modifiers list.
1605 Rest = Rest.ltrim();
1606 } while (Rest.consume_front(","));
1607 if (!Rest.consume_front("}:"))
1608 return {Check::CheckNone, Rest};
1609 return {Ret, Rest};
1610 };
1611
1612 // Verify that the prefix is followed by directive modifiers or a colon.
1613 if (Rest.consume_front(":"))
1614 return {Check::CheckPlain, Rest};
1615 if (Rest.front() == '{')
1616 return ConsumeModifiers(Check::CheckPlain);
1617
1618 if (Rest.consume_front("_"))
1619 Misspelled = true;
1620 else if (!Rest.consume_front("-"))
1621 return {Check::CheckNone, StringRef()};
1622
1623 if (Rest.consume_front("COUNT-")) {
1624 int64_t Count;
1625 if (Rest.consumeInteger(10, Count))
1626 // Error happened in parsing integer.
1627 return {Check::CheckBadCount, Rest};
1628 if (Count <= 0 || Count > INT32_MAX)
1629 return {Check::CheckBadCount, Rest};
1630 if (Rest.front() != ':' && Rest.front() != '{')
1631 return {Check::CheckBadCount, Rest};
1632 return ConsumeModifiers(
1634 }
1635
1636 // You can't combine -NOT with another suffix.
1637 if (Rest.starts_with("DAG-NOT:") || Rest.starts_with("NOT-DAG:") ||
1638 Rest.starts_with("NEXT-NOT:") || Rest.starts_with("NOT-NEXT:") ||
1639 Rest.starts_with("SAME-NOT:") || Rest.starts_with("NOT-SAME:") ||
1640 Rest.starts_with("EMPTY-NOT:") || Rest.starts_with("NOT-EMPTY:"))
1641 return {Check::CheckBadNot, Rest};
1642
1643 if (Rest.consume_front("NEXT"))
1644 return ConsumeModifiers(Check::CheckNext);
1645
1646 if (Rest.consume_front("SAME"))
1647 return ConsumeModifiers(Check::CheckSame);
1648
1649 if (Rest.consume_front("NOT"))
1650 return ConsumeModifiers(Check::CheckNot);
1651
1652 if (Rest.consume_front("DAG"))
1653 return ConsumeModifiers(Check::CheckDAG);
1654
1655 if (Rest.consume_front("LABEL"))
1656 return ConsumeModifiers(Check::CheckLabel);
1657
1658 if (Rest.consume_front("EMPTY"))
1659 return ConsumeModifiers(Check::CheckEmpty);
1660
1661 return {Check::CheckNone, Rest};
1662}
1663
1664static std::pair<Check::FileCheckType, StringRef>
1666 bool Misspelled = false;
1667 auto Res = FindCheckType(Req, Buffer, Prefix, Misspelled);
1668 if (Res.first != Check::CheckNone && Misspelled)
1669 return {Check::CheckMisspelled, Res.second};
1670 return Res;
1671}
1672
1673// From the given position, find the next character after the word.
1674static size_t SkipWord(StringRef Str, size_t Loc) {
1675 while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
1676 ++Loc;
1677 return Loc;
1678}
1679
1680static const char *DefaultCheckPrefixes[] = {"CHECK"};
1681static const char *DefaultCommentPrefixes[] = {"COM", "RUN"};
1682
1684 if (Req.CheckPrefixes.empty()) {
1686 Req.IsDefaultCheckPrefix = true;
1687 }
1688 if (Req.CommentPrefixes.empty())
1690}
1691
1693 /// Prefixes and their first occurrence past the current position.
1696
1698 ArrayRef<StringRef> CommentPrefixes, StringRef Input)
1699 : Input(Input) {
1700 for (StringRef Prefix : CheckPrefixes)
1701 Prefixes.push_back({Prefix, Input.find(Prefix)});
1702 for (StringRef Prefix : CommentPrefixes)
1703 Prefixes.push_back({Prefix, Input.find(Prefix)});
1704
1705 // Sort by descending length.
1707 [](auto A, auto B) { return A.first.size() > B.first.size(); });
1708 }
1709
1710 /// Find the next match of a prefix in Buffer.
1711 /// Returns empty StringRef if not found.
1713 assert(Buffer.data() >= Input.data() &&
1714 Buffer.data() + Buffer.size() == Input.data() + Input.size() &&
1715 "Buffer must be suffix of Input");
1716
1717 size_t From = Buffer.data() - Input.data();
1718 StringRef Match;
1719 for (auto &[Prefix, Pos] : Prefixes) {
1720 // If the last occurrence was before From, find the next one after From.
1721 if (Pos < From)
1722 Pos = Input.find(Prefix, From);
1723 // Find the first prefix with the lowest position.
1724 if (Pos != StringRef::npos &&
1725 (Match.empty() || size_t(Match.data() - Input.data()) > Pos))
1726 Match = StringRef(Input.substr(Pos, Prefix.size()));
1727 }
1728 return Match;
1729 }
1730};
1731
1732/// Searches the buffer for the first prefix in the prefix regular expression.
1733///
1734/// This searches the buffer using the provided regular expression, however it
1735/// enforces constraints beyond that:
1736/// 1) The found prefix must not be a suffix of something that looks like
1737/// a valid prefix.
1738/// 2) The found prefix must be followed by a valid check type suffix using \c
1739/// FindCheckType above.
1740///
1741/// \returns a pair of StringRefs into the Buffer, which combines:
1742/// - the first match of the regular expression to satisfy these two is
1743/// returned,
1744/// otherwise an empty StringRef is returned to indicate failure.
1745/// - buffer rewound to the location right after parsed suffix, for parsing
1746/// to continue from
1747///
1748/// If this routine returns a valid prefix, it will also shrink \p Buffer to
1749/// start at the beginning of the returned prefix, increment \p LineNumber for
1750/// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1751/// check found by examining the suffix.
1752///
1753/// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1754/// is unspecified.
1755static std::pair<StringRef, StringRef>
1757 StringRef &Buffer, unsigned &LineNumber,
1758 Check::FileCheckType &CheckTy) {
1759 while (!Buffer.empty()) {
1760 // Find the first (longest) prefix match.
1761 StringRef Prefix = Matcher.match(Buffer);
1762 if (Prefix.empty())
1763 // No match at all, bail.
1764 return {StringRef(), StringRef()};
1765
1766 assert(Prefix.data() >= Buffer.data() &&
1767 Prefix.data() < Buffer.data() + Buffer.size() &&
1768 "Prefix doesn't start inside of buffer!");
1769 size_t Loc = Prefix.data() - Buffer.data();
1770 StringRef Skipped = Buffer.substr(0, Loc);
1771 Buffer = Buffer.drop_front(Loc);
1772 LineNumber += Skipped.count('\n');
1773
1774 // Check that the matched prefix isn't a suffix of some other check-like
1775 // word.
1776 // FIXME: This is a very ad-hoc check. it would be better handled in some
1777 // other way. Among other things it seems hard to distinguish between
1778 // intentional and unintentional uses of this feature.
1779 if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
1780 // Now extract the type.
1781 StringRef AfterSuffix;
1782 std::tie(CheckTy, AfterSuffix) = FindCheckType(Req, Buffer, Prefix);
1783
1784 // If we've found a valid check type for this prefix, we're done.
1785 if (CheckTy != Check::CheckNone)
1786 return {Prefix, AfterSuffix};
1787 }
1788
1789 // If we didn't successfully find a prefix, we need to skip this invalid
1790 // prefix and continue scanning. We directly skip the prefix that was
1791 // matched and any additional parts of that check-like word.
1792 Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
1793 }
1794
1795 // We ran out of buffer while skipping partial matches so give up.
1796 return {StringRef(), StringRef()};
1797}
1798
1800 assert(!LineVariable && "@LINE pseudo numeric variable already created");
1801 StringRef LineName = "@LINE";
1802 LineVariable = makeNumericVariable(
1804 GlobalNumericVariableTable[LineName] = LineVariable;
1805}
1806
1808 : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()) {}
1809
1810FileCheck::~FileCheck() = default;
1811
1813 SourceMgr &SM, StringRef Buffer,
1814 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1815 if (ImpPatBufferIDRange)
1816 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1817
1818 Error DefineError =
1819 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1820 if (DefineError) {
1821 logAllUnhandledErrors(std::move(DefineError), errs());
1822 return true;
1823 }
1824
1825 PatternContext->createLineVariable();
1826
1827 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1828 for (StringRef PatternString : Req.ImplicitCheckNot) {
1829 // Create a buffer with fake command line content in order to display the
1830 // command line option responsible for the specific implicit CHECK-NOT.
1831 std::string Prefix = "-implicit-check-not='";
1832 std::string Suffix = "'";
1833 std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
1834 (Prefix + PatternString + Suffix).str(), "command line");
1835
1836 StringRef PatternInBuffer =
1837 CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
1838 unsigned BufferID = SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
1839 if (ImpPatBufferIDRange) {
1840 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1841 ImpPatBufferIDRange->first = BufferID;
1842 ImpPatBufferIDRange->second = BufferID + 1;
1843 } else {
1844 assert(BufferID == ImpPatBufferIDRange->second &&
1845 "expected consecutive source buffer IDs");
1846 ++ImpPatBufferIDRange->second;
1847 }
1848 }
1849
1850 ImplicitNegativeChecks.emplace_back(
1851 Pattern(Check::CheckNot, PatternContext.get()),
1852 StringRef("IMPLICIT-CHECK"));
1853 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1854 PatternInBuffer, "IMPLICIT-CHECK", SM, Req);
1855 }
1856
1857 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1858 ImplicitNegativeChecks;
1859 // LineNumber keeps track of the line on which CheckPrefix instances are
1860 // found.
1861 unsigned LineNumber = 1;
1862
1863 addDefaultPrefixes(Req);
1864 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1865 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1866 Req.CheckPrefixes.end());
1867 const size_t DistinctPrefixes = PrefixesNotFound.size();
1868 while (true) {
1869 Check::FileCheckType CheckTy;
1870
1871 // See if a prefix occurs in the memory buffer.
1872 StringRef UsedPrefix;
1873 StringRef AfterSuffix;
1874 std::tie(UsedPrefix, AfterSuffix) =
1875 FindFirstMatchingPrefix(Req, Matcher, Buffer, LineNumber, CheckTy);
1876 if (UsedPrefix.empty())
1877 break;
1878 if (CheckTy != Check::CheckComment)
1879 PrefixesNotFound.erase(UsedPrefix);
1880
1881 assert(UsedPrefix.data() == Buffer.data() &&
1882 "Failed to move Buffer's start forward, or pointed prefix outside "
1883 "of the buffer!");
1884
1885 [[maybe_unused]] const char *BufferEnd = Buffer.data() + Buffer.size();
1886 assert(AfterSuffix.data() >= Buffer.data() &&
1887 AfterSuffix.data() <= BufferEnd &&
1888 "Parsing after suffix doesn't start inside of buffer!");
1889
1890 // Skip the buffer to the end of the parsed directive suffix.
1891 Buffer = AfterSuffix;
1892
1893 // Location to use for error messages.
1894 const char *UsedPrefixStart = UsedPrefix.data();
1895
1896 // Complain about misspelled directives.
1897 if (CheckTy == Check::CheckMisspelled) {
1898 StringRef UsedDirective(UsedPrefix.data(),
1899 AfterSuffix.data() - UsedPrefix.data());
1900 SM.PrintMessage(SMLoc::getFromPointer(UsedDirective.data()),
1902 "misspelled directive '" + UsedDirective + "'");
1903 return true;
1904 }
1905
1906 // Complain about useful-looking but unsupported suffixes.
1907 if (CheckTy == Check::CheckBadNot) {
1908 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
1909 "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
1910 return true;
1911 }
1912
1913 // Complain about invalid count specification.
1914 if (CheckTy == Check::CheckBadCount) {
1915 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
1916 "invalid count in -COUNT specification on prefix '" +
1917 UsedPrefix + "'");
1918 return true;
1919 }
1920
1921 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1922 // leading whitespace.
1923 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1924 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
1925
1926 // Scan ahead to the end of line.
1927 size_t EOL = Buffer.find_first_of("\n\r");
1928
1929 // Remember the location of the start of the pattern, for diagnostics.
1930 SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
1931
1932 // Extract the pattern from the buffer.
1933 StringRef PatternBuffer = Buffer.substr(0, EOL);
1934 Buffer = Buffer.substr(EOL);
1935
1936 // If this is a comment, we're done.
1937 if (CheckTy == Check::CheckComment)
1938 continue;
1939
1940 // Parse the pattern.
1941 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1942 if (P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1943 return true;
1944
1945 // Verify that CHECK-LABEL lines do not define or use variables
1946 if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
1947 SM.PrintMessage(
1949 "found '" + UsedPrefix + "-LABEL:'"
1950 " with variable definition or use");
1951 return true;
1952 }
1953
1954 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1955 if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
1956 CheckTy == Check::CheckEmpty) &&
1957 CheckStrings.empty()) {
1958 StringRef Type = CheckTy == Check::CheckNext
1959 ? "NEXT"
1960 : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
1961 SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
1963 "found '" + UsedPrefix + "-" + Type +
1964 "' without previous '" + UsedPrefix + ": line");
1965 return true;
1966 }
1967
1968 // Handle CHECK-DAG/-NOT.
1969 if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
1970 DagNotMatches.emplace_back(P, UsedPrefix);
1971 continue;
1972 }
1973
1974 // Okay, add the string we captured to the output vector and move on.
1975 CheckStrings.emplace_back(std::move(P), UsedPrefix, PatternLoc,
1976 std::move(DagNotMatches));
1977 DagNotMatches = ImplicitNegativeChecks;
1978 }
1979
1980 // When there are no used prefixes we report an error except in the case that
1981 // no prefix is specified explicitly but -implicit-check-not is specified.
1982 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1983 const bool SomePrefixesUnexpectedlyNotUsed =
1984 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
1985 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1986 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
1987 errs() << "error: no check strings found with prefix"
1988 << (PrefixesNotFound.size() > 1 ? "es " : " ");
1989 ListSeparator LS;
1990 for (StringRef MissingPrefix : PrefixesNotFound)
1991 errs() << LS << "\'" << MissingPrefix << ":'";
1992 errs() << '\n';
1993 return true;
1994 }
1995
1996 // Add an EOF pattern for any trailing --implicit-check-not/CHECK-DAG/-NOTs,
1997 // and use the first prefix as a filler for the error message.
1998 if (!DagNotMatches.empty()) {
1999 CheckStrings.emplace_back(
2000 Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
2001 *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()),
2002 std::move(DagNotMatches));
2003 }
2004
2005 return false;
2006}
2007
2008/// Returns either (1) \c ErrorSuccess if there was no error or (2)
2009/// \c ErrorReported if an error was reported, such as an unexpected match.
2010static Error printMatch(bool ExpectedMatch, const SourceMgr &SM,
2011 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2012 int MatchedCount, StringRef Buffer,
2013 Pattern::MatchResult MatchResult,
2014 const FileCheckRequest &Req, FileCheckDiagList *Diags) {
2015 // Suppress some verbosity if there's no error.
2016 bool HasError = !ExpectedMatch || MatchResult.TheError;
2017 bool PrintDiag = true;
2018 if (!HasError) {
2019 if (!Req.Verbose)
2020 return ErrorReported::reportedOrSuccess(HasError);
2021 if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
2022 return ErrorReported::reportedOrSuccess(HasError);
2023 // Due to their verbosity, we don't print verbose diagnostics here if we're
2024 // gathering them for Diags to be rendered elsewhere, but we always print
2025 // other diagnostics.
2026 PrintDiag = !Diags;
2027 }
2028
2029 // Add "found" diagnostic, substitutions, and variable definitions to Diags.
2032 SMRange MatchRange = buildMatchRange(Buffer, MatchResult.TheMatch->Pos,
2033 MatchResult.TheMatch->Len);
2034 SMRange SearchRange = buildSearchRange(Buffer);
2035 if (Diags) {
2036 Diags->emplace<MatchFoundDiag>(Pat.getCheckTy(), Loc, Status, MatchRange,
2037 SearchRange);
2038 Pat.printSubstitutions(SM, Buffer, MatchRange, Diags);
2039 Pat.printVariableDefs(SM, Diags);
2040 }
2041 if (!PrintDiag) {
2042 assert(!HasError && "expected to report more diagnostics for error");
2043 return ErrorReported::reportedOrSuccess(HasError);
2044 }
2045
2046 // Print the match.
2047 std::string Message = formatv("{0}: {1} string found in input",
2048 Pat.getCheckTy().getDescription(Prefix),
2049 (ExpectedMatch ? "expected" : "excluded"))
2050 .str();
2051 if (Pat.getCount() > 1)
2052 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2053 SM.PrintMessage(
2054 Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
2055 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
2056 {MatchRange});
2057
2058 // Print additional information, which can be useful even if there are errors.
2059 Pat.printSubstitutions(SM, Buffer, MatchRange, nullptr);
2060 Pat.printVariableDefs(SM, nullptr);
2061
2062 // Print errors and add them to Diags. We report these errors after the match
2063 // itself because we found them after the match. If we had found them before
2064 // the match, we'd be in printNoMatch.
2065 handleAllErrors(std::move(MatchResult.TheError),
2066 [&](const ErrorDiagnostic &E) {
2067 E.log(errs());
2068 if (Diags) {
2069 Diags->emplace<MatchCustomNoteDiag>(E.getRange(),
2070 E.getMessage().str(),
2071 /*AddsError=*/true);
2072 }
2073 });
2074 return ErrorReported::reportedOrSuccess(HasError);
2075}
2076
2077/// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2078/// \c ErrorReported if an error was reported, such as an expected match not
2079/// found.
2080static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM,
2081 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2082 int MatchedCount, StringRef Buffer, Error MatchError,
2083 bool VerboseVerbose, FileCheckDiagList *Diags) {
2084 // Print any pattern errors, and record them to be added to Diags later.
2085 bool HasError = ExpectedMatch;
2086 bool HasPatternError = false;
2091 std::move(MatchError),
2092 [&](const ErrorDiagnostic &E) {
2093 HasError = HasPatternError = true;
2095 E.log(errs());
2096 if (Diags)
2097 ErrorMsgs.push_back(E.getMessage().str());
2098 },
2099 // NotFoundError is why printNoMatch was invoked.
2100 [](const NotFoundError &E) {});
2101
2102 // Suppress some verbosity if there's no error.
2103 bool PrintDiag = true;
2104 if (!HasError) {
2105 if (!VerboseVerbose)
2106 return ErrorReported::reportedOrSuccess(HasError);
2107 // Due to their verbosity, we don't print verbose diagnostics here if we're
2108 // gathering them for Diags to be rendered elsewhere, but we always print
2109 // other diagnostics.
2110 PrintDiag = !Diags;
2111 }
2112
2113 // Add "not found" diagnostic, substitutions, and pattern errors to Diags.
2114 //
2115 // We handle Diags a little differently than the errors we print directly:
2116 // we add the "not found" diagnostic to Diags even if there are pattern
2117 // errors. The reason is that we need to attach pattern errors as notes
2118 // somewhere in the input, and the input search range from the "not found"
2119 // diagnostic is all we have to anchor them.
2120 SMRange SearchRange = buildSearchRange(Buffer);
2121 if (Diags) {
2122 Diags->emplace<MatchNoneDiag>(Pat.getCheckTy(), Loc, Status, SearchRange);
2123 for (StringRef ErrorMsg : ErrorMsgs)
2124 Diags->emplace<MatchCustomNoteDiag>(ErrorMsg);
2125 Pat.printSubstitutions(SM, Buffer, SearchRange, Diags);
2126 }
2127 if (!PrintDiag) {
2128 assert(!HasError && "expected to report more diagnostics for error");
2129 return ErrorReported::reportedOrSuccess(HasError);
2130 }
2131
2132 // Print "not found" diagnostic, except that's implied if we already printed a
2133 // pattern error.
2134 if (!HasPatternError) {
2135 std::string Message = formatv("{0}: {1} string not found in input",
2136 Pat.getCheckTy().getDescription(Prefix),
2137 (ExpectedMatch ? "expected" : "excluded"))
2138 .str();
2139 if (Pat.getCount() > 1)
2140 Message +=
2141 formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2142 SM.PrintMessage(Loc,
2143 ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark,
2144 Message);
2145 SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note,
2146 "scanning from here");
2147 }
2148
2149 // Print additional information, which can be useful even after a pattern
2150 // error.
2151 Pat.printSubstitutions(SM, Buffer, SearchRange, nullptr);
2152 if (ExpectedMatch)
2153 Pat.printFuzzyMatch(SM, Buffer, Diags);
2154 return ErrorReported::reportedOrSuccess(HasError);
2155}
2156
2157/// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2158/// \c ErrorReported if an error was reported.
2159static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM,
2160 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2161 int MatchedCount, StringRef Buffer,
2162 Pattern::MatchResult MatchResult,
2163 const FileCheckRequest &Req,
2164 FileCheckDiagList *Diags) {
2165 if (MatchResult.TheMatch)
2166 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2167 std::move(MatchResult), Req, Diags);
2168 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2169 std::move(MatchResult.TheError), Req.VerboseVerbose,
2170 Diags);
2171}
2172
2173/// Counts the number of newlines in the specified range.
2175 const char *&FirstNewLine) {
2176 unsigned NumNewLines = 0;
2177 while (true) {
2178 // Scan for newline.
2179 Range = Range.substr(Range.find_first_of("\n\r"));
2180 if (Range.empty())
2181 return NumNewLines;
2182
2183 ++NumNewLines;
2184
2185 // Handle \n\r and \r\n as a single newline.
2186 if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
2187 (Range[0] != Range[1]))
2188 Range = Range.substr(1);
2189 Range = Range.substr(1);
2190
2191 if (NumNewLines == 1)
2192 FirstNewLine = Range.begin();
2193 }
2194}
2195
2197 bool IsLabelScanMode, size_t &MatchLen,
2198 FileCheckRequest &Req,
2199 FileCheckDiagList *Diags) const {
2200 size_t LastPos = 0;
2201 std::vector<const DagNotPrefixInfo *> NotStrings;
2202
2203 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
2204 // bounds; we have not processed variable definitions within the bounded block
2205 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
2206 // over the block again (including the last CHECK-LABEL) in normal mode.
2207 if (!IsLabelScanMode) {
2208 // Match "dag strings" (with mixed "not strings" if any).
2209 LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
2210 if (LastPos == StringRef::npos)
2211 return StringRef::npos;
2212 }
2213
2214 // Match itself from the last position after matching CHECK-DAG.
2215 size_t LastMatchEnd = LastPos;
2216 size_t FirstMatchPos = 0;
2217 // Go match the pattern Count times. Majority of patterns only match with
2218 // count 1 though.
2219 assert(Pat.getCount() != 0 && "pattern count can not be zero");
2220 for (int i = 1; i <= Pat.getCount(); i++) {
2221 StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
2222 // get a match at current start point
2223 Pattern::MatchResult MatchResult = Pat.match(MatchBuffer, SM);
2224
2225 // report
2226 if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, Prefix, Loc,
2227 Pat, i, MatchBuffer,
2228 std::move(MatchResult), Req, Diags)) {
2229 cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2230 return StringRef::npos;
2231 }
2232
2233 size_t MatchPos = MatchResult.TheMatch->Pos;
2234 if (i == 1)
2235 FirstMatchPos = LastPos + MatchPos;
2236
2237 // move start point after the match
2238 LastMatchEnd += MatchPos + MatchResult.TheMatch->Len;
2239 }
2240 // Full match len counts from first match pos.
2241 MatchLen = LastMatchEnd - FirstMatchPos;
2242
2243 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
2244 // or CHECK-NOT
2245 if (!IsLabelScanMode) {
2246 size_t MatchPos = FirstMatchPos - LastPos;
2247 StringRef MatchBuffer = Buffer.substr(LastPos);
2248 StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
2249
2250 // If this check is a "CHECK-NEXT", verify that the previous match was on
2251 // the previous line (i.e. that there is one newline between them).
2252 if (CheckNext(SM, SkippedRegion)) {
2253 if (Diags) {
2254 if (Req.Verbose) {
2256 } else {
2257 Diags->emplace<MatchFoundDiag>(
2258 Pat.getCheckTy(), Loc, MatchFoundDiag::WrongLine,
2259 buildMatchRange(MatchBuffer, MatchPos, MatchLen),
2260 buildSearchRange(MatchBuffer));
2261 }
2262 }
2263 return StringRef::npos;
2264 }
2265
2266 // If this check is a "CHECK-SAME", verify that the previous match was on
2267 // the same line (i.e. that there is no newline between them).
2268 if (CheckSame(SM, SkippedRegion)) {
2269 if (Diags) {
2270 if (Req.Verbose) {
2272 } else {
2273 Diags->emplace<MatchFoundDiag>(
2274 Pat.getCheckTy(), Loc, MatchFoundDiag::WrongLine,
2275 buildMatchRange(MatchBuffer, MatchPos, MatchLen),
2276 buildSearchRange(MatchBuffer));
2277 }
2278 }
2279 return StringRef::npos;
2280 }
2281
2282 // If this match had "not strings", verify that they don't exist in the
2283 // skipped region.
2284 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2285 return StringRef::npos;
2286 }
2287
2288 return FirstMatchPos;
2289}
2290
2292 if (Pat.getCheckTy() != Check::CheckNext &&
2293 Pat.getCheckTy() != Check::CheckEmpty)
2294 return false;
2295
2296 Twine CheckName =
2297 Prefix +
2298 Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
2299
2300 // Count the number of newlines between the previous match and this one.
2301 const char *FirstNewLine = nullptr;
2302 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
2303
2304 if (NumNewLines == 0) {
2305 SM.PrintMessage(Loc, SourceMgr::DK_Error,
2306 CheckName + ": is on the same line as previous match");
2307 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
2308 "'next' match was here");
2309 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
2310 "previous match ended here");
2311 return true;
2312 }
2313
2314 if (NumNewLines != 1) {
2315 SM.PrintMessage(Loc, SourceMgr::DK_Error,
2316 CheckName +
2317 ": is not on the line after the previous match");
2318 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
2319 "'next' match was here");
2320 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
2321 "previous match ended here");
2322 SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
2323 "non-matching line after previous match is here");
2324 return true;
2325 }
2326
2327 return false;
2328}
2329
2331 if (Pat.getCheckTy() != Check::CheckSame)
2332 return false;
2333
2334 // Count the number of newlines between the previous match and this one.
2335 const char *FirstNewLine = nullptr;
2336 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
2337
2338 if (NumNewLines != 0) {
2339 SM.PrintMessage(Loc, SourceMgr::DK_Error,
2340 Prefix +
2341 "-SAME: is not on the same line as the previous match");
2342 SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
2343 "'next' match was here");
2344 SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
2345 "previous match ended here");
2346 return true;
2347 }
2348
2349 return false;
2350}
2351
2353 const SourceMgr &SM, StringRef Buffer,
2354 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2355 const FileCheckRequest &Req, FileCheckDiagList *Diags) const {
2356 bool DirectiveFail = false;
2357 for (auto NotInfo : NotStrings) {
2358 assert((NotInfo->DagNotPat.getCheckTy() == Check::CheckNot) &&
2359 "Expect CHECK-NOT!");
2360 Pattern::MatchResult MatchResult = NotInfo->DagNotPat.match(Buffer, SM);
2361 if (Error Err = reportMatchResult(
2362 /*ExpectedMatch=*/false, SM, NotInfo->DagNotPrefix,
2363 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2364 std::move(MatchResult), Req, Diags)) {
2365 cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2366 DirectiveFail = true;
2367 continue;
2368 }
2369 }
2370 return DirectiveFail;
2371}
2372
2373size_t
2375 std::vector<const DagNotPrefixInfo *> &NotStrings,
2376 const FileCheckRequest &Req,
2377 FileCheckDiagList *Diags) const {
2378 if (DagNotStrings.empty())
2379 return 0;
2380
2381 // The start of the search range.
2382 size_t StartPos = 0;
2383
2384 struct MatchRange {
2385 size_t Pos;
2386 size_t End;
2387 };
2388 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
2389 // ranges are erased from this list once they are no longer in the search
2390 // range.
2391 std::list<MatchRange> MatchRanges;
2392
2393 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
2394 // group, so we don't use a range-based for loop here.
2395 for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
2396 PatItr != PatEnd; ++PatItr) {
2397 const Pattern &Pat = PatItr->DagNotPat;
2398 const StringRef DNPrefix = PatItr->DagNotPrefix;
2399 assert((Pat.getCheckTy() == Check::CheckDAG ||
2400 Pat.getCheckTy() == Check::CheckNot) &&
2401 "Invalid CHECK-DAG or CHECK-NOT!");
2402
2403 if (Pat.getCheckTy() == Check::CheckNot) {
2404 NotStrings.push_back(&*PatItr);
2405 continue;
2406 }
2407
2408 assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
2409
2410 // CHECK-DAG always matches from the start.
2411 size_t MatchLen = 0, MatchPos = StartPos;
2412
2413 // Search for a match that doesn't overlap a previous match in this
2414 // CHECK-DAG group.
2415 for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
2416 StringRef MatchBuffer = Buffer.substr(MatchPos);
2417 Pattern::MatchResult MatchResult = Pat.match(MatchBuffer, SM);
2418 // With a group of CHECK-DAGs, a single mismatching means the match on
2419 // that group of CHECK-DAGs fails immediately.
2420 if (MatchResult.TheError || Req.VerboseVerbose) {
2421 if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, DNPrefix,
2422 Pat.getLoc(), Pat, 1, MatchBuffer,
2423 std::move(MatchResult), Req, Diags)) {
2424 cantFail(
2425 handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2426 return StringRef::npos;
2427 }
2428 }
2429 MatchLen = MatchResult.TheMatch->Len;
2430 // Re-calc it as the offset relative to the start of the original
2431 // string.
2432 MatchPos += MatchResult.TheMatch->Pos;
2433 MatchRange M{MatchPos, MatchPos + MatchLen};
2434 if (Req.AllowDeprecatedDagOverlap) {
2435 // We don't need to track all matches in this mode, so we just maintain
2436 // one match range that encompasses the current CHECK-DAG group's
2437 // matches.
2438 if (MatchRanges.empty())
2439 MatchRanges.insert(MatchRanges.end(), M);
2440 else {
2441 auto Block = MatchRanges.begin();
2442 Block->Pos = std::min(Block->Pos, M.Pos);
2443 Block->End = std::max(Block->End, M.End);
2444 }
2445 break;
2446 }
2447 // Iterate previous matches until overlapping match or insertion point.
2448 bool Overlap = false;
2449 for (; MI != ME; ++MI) {
2450 if (M.Pos < MI->End) {
2451 // !Overlap => New match has no overlap and is before this old match.
2452 // Overlap => New match overlaps this old match.
2453 Overlap = MI->Pos < M.End;
2454 break;
2455 }
2456 }
2457 if (!Overlap) {
2458 // Insert non-overlapping match into list.
2459 MatchRanges.insert(MI, M);
2460 break;
2461 }
2462 if (Req.VerboseVerbose) {
2463 // Due to their verbosity, we don't print verbose diagnostics here if
2464 // we're gathering them for a different rendering, but we always print
2465 // other diagnostics.
2466 if (Diags) {
2468 } else {
2469 SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
2470 SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
2471 SMRange OldRange(OldStart, OldEnd);
2472 SM.PrintMessage(OldStart, SourceMgr::DK_Note,
2473 "match discarded, overlaps earlier DAG match here",
2474 {OldRange});
2475 }
2476 }
2477 MatchPos = MI->End;
2478 }
2479 if (!Req.VerboseVerbose)
2481 /*ExpectedMatch=*/true, SM, DNPrefix, Pat.getLoc(), Pat, 1, Buffer,
2482 Pattern::MatchResult(MatchPos, MatchLen, Error::success()), Req,
2483 Diags));
2484
2485 // Handle the end of a CHECK-DAG group.
2486 if (std::next(PatItr) == PatEnd ||
2487 std::next(PatItr)->DagNotPat.getCheckTy() == Check::CheckNot) {
2488 if (!NotStrings.empty()) {
2489 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
2490 // CHECK-DAG, verify that there are no 'not' strings occurred in that
2491 // region.
2492 StringRef SkippedRegion =
2493 Buffer.slice(StartPos, MatchRanges.begin()->Pos);
2494 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2495 return StringRef::npos;
2496 // Clear "not strings".
2497 NotStrings.clear();
2498 }
2499 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
2500 // end of this CHECK-DAG group's match range.
2501 StartPos = MatchRanges.rbegin()->End;
2502 // Don't waste time checking for (impossible) overlaps before that.
2503 MatchRanges.clear();
2504 }
2505 }
2506
2507 return StartPos;
2508}
2509
2510static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes,
2511 ArrayRef<StringRef> SuppliedPrefixes) {
2512 for (StringRef Prefix : SuppliedPrefixes) {
2513 if (Prefix.empty()) {
2514 errs() << "error: supplied " << Kind << " prefix must not be the empty "
2515 << "string\n";
2516 return false;
2517 }
2518 static const Regex Validator("^[a-zA-Z0-9_-]*$");
2519 if (!Validator.match(Prefix)) {
2520 errs() << "error: supplied " << Kind << " prefix must start with a "
2521 << "letter and contain only alphanumeric characters, hyphens, and "
2522 << "underscores: '" << Prefix << "'\n";
2523 return false;
2524 }
2525 if (!UniquePrefixes.insert(Prefix).second) {
2526 errs() << "error: supplied " << Kind << " prefix must be unique among "
2527 << "check and comment prefixes: '" << Prefix << "'\n";
2528 return false;
2529 }
2530 }
2531 return true;
2532}
2533
2535 StringSet<> UniquePrefixes;
2536 // Add default prefixes to catch user-supplied duplicates of them below.
2537 if (Req.CheckPrefixes.empty())
2538 UniquePrefixes.insert_range(DefaultCheckPrefixes);
2539 if (Req.CommentPrefixes.empty())
2540 UniquePrefixes.insert_range(DefaultCommentPrefixes);
2541 // Do not validate the default prefixes, or diagnostics about duplicates might
2542 // incorrectly indicate that they were supplied by the user.
2543 if (!ValidatePrefixes("check", UniquePrefixes, Req.CheckPrefixes))
2544 return false;
2545 if (!ValidatePrefixes("comment", UniquePrefixes, Req.CommentPrefixes))
2546 return false;
2547 return true;
2548}
2549
2551 ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM) {
2552 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2553 "Overriding defined variable with command-line variable definitions");
2554
2555 if (CmdlineDefines.empty())
2556 return Error::success();
2557
2558 // Create a string representing the vector of command-line definitions. Each
2559 // definition is on its own line and prefixed with a definition number to
2560 // clarify which definition a given diagnostic corresponds to.
2561 unsigned I = 0;
2562 Error Errs = Error::success();
2563 std::string CmdlineDefsDiag;
2564 SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;
2565 for (StringRef CmdlineDef : CmdlineDefines) {
2566 std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
2567 size_t EqIdx = CmdlineDef.find('=');
2568 if (EqIdx == StringRef::npos) {
2569 CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2570 continue;
2571 }
2572 // Numeric variable definition.
2573 if (CmdlineDef[0] == '#') {
2574 // Append a copy of the command-line definition adapted to use the same
2575 // format as in the input file to be able to reuse
2576 // parseNumericSubstitutionBlock.
2577 CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
2578 std::string SubstitutionStr = std::string(CmdlineDef);
2579 SubstitutionStr[EqIdx] = ':';
2580 CmdlineDefsIndices.push_back(
2581 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2582 CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
2583 } else {
2584 CmdlineDefsDiag += DefPrefix;
2585 CmdlineDefsIndices.push_back(
2586 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2587 CmdlineDefsDiag += (CmdlineDef + "\n").str();
2588 }
2589 }
2590
2591 // Create a buffer with fake command line content in order to display
2592 // parsing diagnostic with location information and point to the
2593 // global definition with invalid syntax.
2594 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2595 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");
2596 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2597 SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
2598
2599 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2600 StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
2601 CmdlineDefIndices.second);
2602 if (CmdlineDef.empty()) {
2603 Errs = joinErrors(
2604 std::move(Errs),
2605 ErrorDiagnostic::get(SM, CmdlineDef,
2606 "missing equal sign in global definition"));
2607 continue;
2608 }
2609
2610 // Numeric variable definition.
2611 if (CmdlineDef[0] == '#') {
2612 // Now parse the definition both to check that the syntax is correct and
2613 // to create the necessary class instance.
2614 StringRef CmdlineDefExpr = CmdlineDef.substr(1);
2615 std::optional<NumericVariable *> DefinedNumericVariable;
2616 Expected<std::unique_ptr<Expression>> ExpressionResult =
2618 DefinedNumericVariable, false,
2619 std::nullopt, this, SM);
2620 if (!ExpressionResult) {
2621 Errs = joinErrors(std::move(Errs), ExpressionResult.takeError());
2622 continue;
2623 }
2624 std::unique_ptr<Expression> Expression = std::move(*ExpressionResult);
2625 // Now evaluate the expression whose value this variable should be set
2626 // to, since the expression of a command-line variable definition should
2627 // only use variables defined earlier on the command-line. If not, this
2628 // is an error and we report it.
2630 if (!Value) {
2631 Errs = joinErrors(std::move(Errs), Value.takeError());
2632 continue;
2633 }
2634
2635 assert(DefinedNumericVariable && "No variable defined");
2636 (*DefinedNumericVariable)->setValue(*Value);
2637
2638 // Record this variable definition.
2639 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2640 *DefinedNumericVariable;
2641 } else {
2642 // String variable definition.
2643 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
2644 StringRef CmdlineName = CmdlineNameVal.first;
2645 StringRef OrigCmdlineName = CmdlineName;
2647 Pattern::parseVariable(CmdlineName, SM);
2648 if (!ParseVarResult) {
2649 Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());
2650 continue;
2651 }
2652 // Check that CmdlineName does not denote a pseudo variable is only
2653 // composed of the parsed numeric variable. This catches cases like
2654 // "FOO+2" in a "FOO+2=10" definition.
2655 if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
2656 Errs = joinErrors(std::move(Errs),
2658 SM, OrigCmdlineName,
2659 "invalid name in string variable definition '" +
2660 OrigCmdlineName + "'"));
2661 continue;
2662 }
2663 StringRef Name = ParseVarResult->Name;
2664
2665 // Detect collisions between string and numeric variables when the former
2666 // is created later than the latter.
2667 if (GlobalNumericVariableTable.contains(Name)) {
2668 Errs = joinErrors(std::move(Errs),
2670 "numeric variable with name '" +
2671 Name + "' already exists"));
2672 continue;
2673 }
2674 GlobalVariableTable.insert(CmdlineNameVal);
2675 // Mark the string variable as defined to detect collisions between
2676 // string and numeric variables in defineCmdlineVariables when the latter
2677 // is created later than the former. We cannot reuse GlobalVariableTable
2678 // for this by populating it with an empty string since we would then
2679 // lose the ability to detect the use of an undefined variable in
2680 // match().
2681 DefinedVariableTable[Name] = true;
2682 }
2683 }
2684
2685 return Errs;
2686}
2687
2689 SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;
2690 for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)
2691 if (Var.first()[0] != '$')
2692 LocalPatternVars.push_back(Var.first());
2693
2694 // Numeric substitution reads the value of a variable directly, not via
2695 // GlobalNumericVariableTable. Therefore, we clear local variables by
2696 // clearing their value which will lead to a numeric substitution failure. We
2697 // also mark the variable for removal from GlobalNumericVariableTable since
2698 // this is what defineCmdlineVariables checks to decide that no global
2699 // variable has been defined.
2700 for (const auto &Var : GlobalNumericVariableTable)
2701 if (Var.first()[0] != '$') {
2702 Var.getValue()->clearValue();
2703 LocalNumericVars.push_back(Var.first());
2704 }
2705
2706 for (const auto &Var : LocalPatternVars)
2707 GlobalVariableTable.erase(Var);
2708 for (const auto &Var : LocalNumericVars)
2709 GlobalNumericVariableTable.erase(Var);
2710}
2711
2713 FileCheckDiagList *Diags) {
2714 bool ChecksFailed = false;
2715
2716 unsigned i = 0, j = 0, e = CheckStrings.size();
2717 while (true) {
2718 StringRef CheckRegion;
2719 if (j == e) {
2720 CheckRegion = Buffer;
2721 } else {
2722 const FileCheckString &CheckLabelStr = CheckStrings[j];
2723 if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
2724 ++j;
2725 continue;
2726 }
2727
2728 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
2729 size_t MatchLabelLen = 0;
2730 size_t MatchLabelPos =
2731 CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
2732 if (MatchLabelPos == StringRef::npos)
2733 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
2734 return false;
2735
2736 CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
2737 Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
2738 ++j;
2739 }
2740
2741 // Do not clear the first region as it's the one before the first
2742 // CHECK-LABEL and it would clear variables defined on the command-line
2743 // before they get used.
2744 if (i != 0 && Req.EnableVarScope)
2745 PatternContext->clearLocalVars();
2746
2747 for (; i != j; ++i) {
2748 const FileCheckString &CheckStr = CheckStrings[i];
2749
2750 // Check each string within the scanned region, including a second check
2751 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
2752 size_t MatchLen = 0;
2753 size_t MatchPos =
2754 CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
2755
2756 if (MatchPos == StringRef::npos) {
2757 ChecksFailed = true;
2758 i = j;
2759 break;
2760 }
2761
2762 CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
2763 }
2764
2765 if (j == e)
2766 break;
2767 }
2768
2769 // Success if no checks failed.
2770 return !ChecksFailed;
2771}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, PrefixMatcher &Matcher, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
static Error printMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error or (2) ErrorReported if an error was reported,...
static size_t SkipWord(StringRef Str, size_t Loc)
static SMRange buildMatchRange(StringRef Buffer, size_t Pos, size_t Len)
static SMRange buildSearchRange(StringRef Buffer)
static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported.
static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Error MatchError, bool VerboseVerbose, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported,...
static char popFront(StringRef &S)
constexpr StringLiteral SpaceChars
static std::pair< Check::FileCheckType, StringRef > FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix, bool &Misspelled)
static const char * DefaultCheckPrefixes[]
static const char * DefaultCommentPrefixes[]
static unsigned CountNumNewlinesBetween(StringRef Range, const char *&FirstNewLine)
Counts the number of newlines in the specified range.
static APInt toSigned(APInt AbsVal, bool Negative)
static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, ArrayRef< StringRef > SuppliedPrefixes)
static void addDefaultPrefixes(FileCheckRequest &Req)
static unsigned nextAPIntBitWidth(unsigned BitWidth)
static constexpr int BackrefLimit
Definition FileCheck.cpp:31
static bool IsPartOfWord(char c)
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
nvptx lower args
static constexpr unsigned SM(unsigned Version)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1055
APInt abs() const
Get the absolute value.
Definition APInt.h:1818
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1511
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:330
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1980
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:2006
static constexpr unsigned APINT_BITS_PER_WORD
Bits in a word.
Definition APInt.h:86
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:2012
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1028
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:342
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition APInt.h:1137
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1993
LLVM_ABI void toString(SmallVectorImpl< char > &Str, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false) const
Converts an APInt to a string and append it to Str.
Definition APInt.cpp:2216
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Expected< ExpressionFormat > getImplicitFormat(const SourceMgr &SM) const override
Expected< APInt > eval() const override
Evaluates the value of the binary operation represented by this AST, using EvalBinop on the result of...
LLVM_ABI std::string getDescription(StringRef Prefix) const
bool isLiteralMatch() const
Definition FileCheck.h:99
LLVM_ABI std::string getModifiersDescription() const
LLVM_ABI FileCheckType & setCount(int C)
Class to represent an error holding a diagnostic with location information used when printing it.
static LLVM_ABI_FOR_TEST char ID
static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg, SMRange Range={})
An error that has already been reported.
static Error reportedOrSuccess(bool HasErrorReported)
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
virtual Expected< APInt > eval() const =0
Evaluates and.
StringRef getExpressionStr() const
Class representing an expression and its matching format.
ExpressionAST * getAST() const
A FileCheckDiag series emitted by the FileCheck library.
Definition FileCheck.h:401
void emplace(ArgTys &&...Args)
Emplace a new FileCheckDiag of type DiagTy.
Definition FileCheck.h:415
void adjustPrevMatchFoundDiag(MatchFoundDiag::StatusTy Status)
Adjust the previous MatchResultDiag, which must be a MatchFoundDiag, from successful status to unsucc...
Definition FileCheck.h:430
virtual ~FileCheckDiag()=0
Destructor is purely virtual to ensure this remains an abstract class.
Class holding the Pattern global state, shared by all patterns: tables holding values of variables an...
LLVM_ABI_FOR_TEST Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
LLVM_ABI_FOR_TEST void createLineVariable()
Create @LINE pseudo variable.
LLVM_ABI_FOR_TEST Expected< StringRef > getPatternVarValue(StringRef VarName)
LLVM_ABI_FOR_TEST void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
LLVM_ABI bool readCheckFile(SourceMgr &SM, StringRef Buffer, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
LLVM_ABI StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
LLVM_ABI FileCheck(FileCheckRequest Req)
LLVM_ABI ~FileCheck()
LLVM_ABI bool checkInput(SourceMgr &SM, StringRef Buffer, FileCheckDiagList *Diags=nullptr)
Checks the input to FileCheck provided in the Buffer against the expected strings read from the check...
LLVM_ABI bool ValidateCheckPrefixes()
A helper class to return the specified delimiter string after the first invocation of operator String...
MatchNoteDiag with a custom note not described by any other class derived from MatchNoteDiag.
Definition FileCheck.h:350
MatchResultDiag for a pattern that matched the input.
Definition FileCheck.h:206
@ Success
Indicates a good match for an expected pattern.
Definition FileCheck.h:210
@ Excluded
Indicates a match for an excluded pattern (error).
Definition FileCheck.h:212
@ Discarded
Indicates a discarded match for an expected pattern (not an error).
Definition FileCheck.h:217
@ WrongLine
Indicates a match for an expected pattern, but the match is on the wrong line (error).
Definition FileCheck.h:215
MatchNoteDiag for a fuzzy match that serves as a suggestion for the next intended match for an expect...
Definition FileCheck.h:327
MatchResultDiag for a pattern that did not match the input.
Definition FileCheck.h:264
@ Expected
Indicates no match for an expected pattern (error).
Definition FileCheck.h:276
@ Success
Indicates no match for an excluded pattern.
Definition FileCheck.h:268
@ InvalidPattern
Indicates no match due to an expected or excluded pattern that has proven to be invalid at match time...
Definition FileCheck.h:272
virtual ~MatchNoteDiag()=0
Destructor is purely virtual to ensure this remains an abstract class.
virtual ~MatchResultDiag()=0
Destructor is purely virtual to ensure this remains an abstract class.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
const char * getBufferEnd() const
const char * getBufferStart() const
static LLVM_ABI_FOR_TEST char ID
Expected< std::string > getResultForDiagnostics() const override
Expected< std::string > getResultRegex() const override
Expected< APInt > eval() const override
Class representing a numeric variable and its associated current value.
void setValue(APInt NewValue, std::optional< StringRef > NewStrValue=std::nullopt)
Sets value of this numeric variable to NewValue, and sets the input buffer string from which it was p...
ExpressionFormat getImplicitFormat() const
std::optional< size_t > getDefLineNumber() const
Class to represent an overflow error that might result when manipulating a value.
static LLVM_ABI_FOR_TEST char ID
This class represents success/failure for parsing-like operations that find it important to chain tog...
static LLVM_ABI_FOR_TEST Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< Expression > > parseNumericSubstitutionBlock(StringRef Expr, std::optional< NumericVariable * > &DefinedNumericVariable, bool IsLegacyLineExpr, std::optional< size_t > LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM)
Parses Expr for a numeric substitution block at line LineNumber, or before input is parsed if LineNum...
LLVM_ABI_FOR_TEST void printVariableDefs(const SourceMgr &SM, FileCheckDiagList *Diags) const
static LLVM_ABI_FOR_TEST bool isValidVarNameStart(char C)
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, FileCheckDiagList *Diags) const
void printSubstitutions(const SourceMgr &SM, StringRef Buffer, SMRange MatchRange, FileCheckDiagList *Diags) const
Prints the value of successful substitutions.
int getCount() const
Check::FileCheckType getCheckTy() const
LLVM_ABI_FOR_TEST bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, const FileCheckRequest &Req)
Parses the pattern in PatternStr and initializes this Pattern instance accordingly.
@ Newline
Compile for newline-sensitive matching.
Definition Regex.h:40
@ IgnoreCase
Compile for matching that ignores upper/lower case distinctions.
Definition Regex.h:34
static LLVM_ABI std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
Definition Regex.cpp:239
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition Regex.cpp:83
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
Represents a range in source code.
Definition SMLoc.h:47
SMLoc Start
Definition SMLoc.h:49
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition SourceMgr.h:37
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:882
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:730
static constexpr size_t npos
Definition StringRef.h:58
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition StringRef.h:519
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:629
LLVM_ABI unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
Definition StringRef.cpp:88
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition StringRef.h:714
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
char front() const
Get the first character in the string.
Definition StringRef.h:147
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition StringRef.h:820
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition StringRef.h:396
iterator end() const
Definition StringRef.h:116
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
Definition StringRef.h:832
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition StringRef.h:600
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:290
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition StringRef.h:844
LLVM_ABI size_t find_insensitive(char C, size_t From=0) const
Search for the first character C in the string, ignoring case.
Definition StringRef.cpp:51
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:655
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:636
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition StringSet.h:25
void insert_range(Range &&R)
Definition StringSet.h:49
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:39
Expected< std::string > getResultRegex() const override
Expected< std::string > getResultForDiagnostics() const override
Class representing a substitution to perform in the RegExStr string.
StringRef getFromString() const
size_t getIndex() const
FileCheckPatternContext * Context
Pointer to a class instance holding, among other things, the table with the values of live string var...
virtual Expected< std::string > getResultRegex() const =0
virtual Expected< std::string > getResultForDiagnostics() const =0
StringRef FromStr
The string that needs to be substituted for something else.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
Class to represent an undefined variable error, which quotes that variable's name when printed.
static LLVM_ABI_FOR_TEST char ID
LLVM Value Representation.
Definition Value.h:75
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ CheckBadNot
Marks when parsing found a -NOT check combined with another CHECK suffix.
Definition FileCheck.h:69
@ CheckBadCount
Marks when parsing found a -COUNT directive with invalid count value.
Definition FileCheck.h:72
@ CheckEOF
Indicates the pattern only matches the end of file.
Definition FileCheck.h:66
@ CheckMisspelled
Definition FileCheck.h:54
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:557
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition Error.cpp:61
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition Error.h:1013
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition Error.h:990
LLVM_ABI_FOR_TEST Expected< APInt > exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Performs operation and.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2207
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1745
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Expected< APInt >(*)(const APInt &, const APInt &, bool &) binop_eval_t
Type of functions evaluating a given binary operation.
bool isAlpha(char C)
Checks if character C is a valid letter as classified by "C" locale.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition Error.h:442
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1635
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
constexpr unsigned BitWidth
bool isPrint(char C)
Checks whether character C is printable.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
Expected< APInt > exprMax(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI_FOR_TEST Expected< APInt > exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Expected< APInt > exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI_FOR_TEST Expected< APInt > exprSub(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:874
StringRef match(StringRef Buffer)
Find the next match of a prefix in Buffer.
StringRef Input
SmallVector< std::pair< StringRef, size_t > > Prefixes
Prefixes and their first occurrence past the current position.
PrefixMatcher(ArrayRef< StringRef > CheckPrefixes, ArrayRef< StringRef > CommentPrefixes, StringRef Input)
Type representing the format an expression value should be textualized into for matching.
LLVM_ABI_FOR_TEST APInt valueFromStringRepr(StringRef StrVal, const SourceMgr &SM) const
StringRef toString() const
Definition FileCheck.cpp:33
LLVM_ABI_FOR_TEST Expected< std::string > getMatchingString(APInt Value) const
Definition FileCheck.cpp:82
LLVM_ABI_FOR_TEST Expected< std::string > getWildcardRegex() const
Definition FileCheck.cpp:49
@ HexLower
Value should be printed as a lowercase hex number.
@ HexUpper
Value should be printed as an uppercase hex number.
@ Signed
Value is a signed integer and should be printed as a decimal number.
@ Unsigned
Value is an unsigned integer and should be printed as a decimal number.
@ NoFormat
Denote absence of format.
Contains info about various FileCheck options.
Definition FileCheck.h:33
std::vector< StringRef > CommentPrefixes
Definition FileCheck.h:35
std::vector< StringRef > CheckPrefixes
Definition FileCheck.h:34
A check that we found in the input file.
bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, FileCheckDiagList *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is a single line in the given Buffer.
Pattern Pat
The pattern to match.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, FileCheckDiagList *Diags) const
Matches "dag strings" and their mixed "not strings".
bool CheckSame(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is no newline in the given Buffer.
std::vector< DagNotPrefixInfo > DagNotStrings
Hold the DAG/NOT strings occurring in the input file.
SMLoc Loc
The location in the match file that the check string was specified.
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, size_t &MatchLen, FileCheckRequest &Req, FileCheckDiagList *Diags) const
Matches check string and its "not strings" and/or "dag strings".
StringRef Prefix
Which prefix name this check matched.
std::optional< Match > TheMatch
Parsing information about a variable.