LLVM 24.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)
259 SM, getExpressionStr(),
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) {
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)) {
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) {
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;
1301 OS << "pattern attempts to capture variables: ";
1303 for (const auto &Def : VariableDefs)
1304 OS << LS << '"' << Def.first << '"';
1305 for (const auto &Def : NumericVariableDefs)
1306 OS << LS << '"' << Def.getKey() << '"';
1307 SMLoc Start = SMLoc::getFromPointer(Buffer.data());
1308 if (Diags)
1309 Diags->emplace<MatchCustomNoteDiag>(OS.str());
1310 else
1311 SM.PrintMessage(Start, SourceMgr::DK_Note, OS.str());
1312}
1313
1315 FileCheckDiagList *Diags) const {
1316 if (VariableDefs.empty() && NumericVariableDefs.empty())
1317 return;
1318 // Build list of variable captures.
1319 struct VarCapture {
1320 StringRef Name;
1321 SMRange Range;
1322 };
1323 SmallVector<VarCapture, 2> VarCaptures;
1324 for (const auto &VariableDef : VariableDefs) {
1325 VarCapture VC;
1326 VC.Name = VariableDef.first;
1327 StringRef Value = Context->GlobalVariableTable[VC.Name];
1328 SMLoc Start = SMLoc::getFromPointer(Value.data());
1329 SMLoc End = SMLoc::getFromPointer(Value.data() + Value.size());
1330 VC.Range = SMRange(Start, End);
1331 VarCaptures.push_back(VC);
1332 }
1333 for (const auto &VariableDef : NumericVariableDefs) {
1334 VarCapture VC;
1335 VC.Name = VariableDef.getKey();
1336 std::optional<StringRef> StrValue =
1337 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1338 if (!StrValue)
1339 continue;
1340 SMLoc Start = SMLoc::getFromPointer(StrValue->data());
1341 SMLoc End = SMLoc::getFromPointer(StrValue->data() + StrValue->size());
1342 VC.Range = SMRange(Start, End);
1343 VarCaptures.push_back(VC);
1344 }
1345 // Sort variable captures by the order in which they matched the input.
1346 // Ranges shouldn't be overlapping, so we can just compare the start.
1347 llvm::sort(VarCaptures, [](const VarCapture &A, const VarCapture &B) {
1348 if (&A == &B)
1349 return false;
1350 assert(A.Range.Start != B.Range.Start &&
1351 "unexpected overlapping variable captures");
1352 return A.Range.Start.getPointer() < B.Range.Start.getPointer();
1353 });
1354 // Create notes for the sorted captures.
1355 for (const VarCapture &VC : VarCaptures) {
1358 OS << "captured var \"" << VC.Name << "\"";
1359 if (Diags)
1360 Diags->emplace<MatchCustomNoteDiag>(VC.Range, OS.str());
1361 else
1362 SM.PrintMessage(VC.Range.Start, SourceMgr::DK_Note, OS.str(), VC.Range);
1363 }
1364}
1365
1366static SMRange buildMatchRange(StringRef Buffer, size_t Pos, size_t Len) {
1367 return SMRange(SMLoc::getFromPointer(Buffer.data() + Pos),
1368 SMLoc::getFromPointer(Buffer.data() + Pos + Len));
1369}
1370
1372 return SMRange(SMLoc::getFromPointer(Buffer.data()),
1373 SMLoc::getFromPointer(Buffer.data() + Buffer.size()));
1374}
1375
1377 FileCheckDiagList *Diags) const {
1378 // Attempt to find the closest/best fuzzy match. Usually an error happens
1379 // because some string in the output didn't exactly match. In these cases, we
1380 // would like to show the user a best guess at what "should have" matched, to
1381 // save them having to actually check the input manually.
1382 size_t NumLinesForward = 0;
1383 size_t Best = StringRef::npos;
1384 double BestQuality = 0;
1385
1386 // Arbitrarily limit quadratic search behavior stemming from long CHECK lines.
1387 if (size_t(4096) * size_t(2048) <
1388 std::min(size_t(4096), Buffer.size()) *
1389 std::max(FixedStr.size(), RegExStr.size()))
1390 return;
1391
1392 // Use an arbitrary 4k limit on how far we will search.
1393 for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
1394 if (Buffer[i] == '\n')
1395 ++NumLinesForward;
1396
1397 // Patterns have leading whitespace stripped, so skip whitespace when
1398 // looking for something which looks like a pattern.
1399 if (Buffer[i] == ' ' || Buffer[i] == '\t')
1400 continue;
1401
1402 // Compute the "quality" of this match as an arbitrary combination of the
1403 // match distance and the number of lines skipped to get to this match.
1404 unsigned Distance = computeMatchDistance(Buffer.substr(i));
1405 double Quality = Distance + (NumLinesForward / 100.);
1406
1407 if (Quality < BestQuality || Best == StringRef::npos) {
1408 Best = i;
1409 BestQuality = Quality;
1410 }
1411 }
1412
1413 // Print the "possible intended match here" line if we found something
1414 // reasonable and not equal to what we showed in the "scanning from here"
1415 // line.
1416 if (Best && Best != StringRef::npos && BestQuality < 50) {
1417 SMLoc MatchStart = SMLoc::getFromPointer(Buffer.data() + Best);
1418 if (Diags)
1419 Diags->emplace<MatchFuzzyDiag>(MatchStart);
1420 SM.PrintMessage(MatchStart, SourceMgr::DK_Note,
1421 "possible intended match here");
1422
1423 // FIXME: If we wanted to be really friendly we would show why the match
1424 // failed, as it can be hard to spot simple one character differences.
1425 }
1426}
1427
1430 auto VarIter = GlobalVariableTable.find(VarName);
1431 if (VarIter == GlobalVariableTable.end())
1432 return make_error<UndefVarError>(VarName);
1433
1434 return VarIter->second;
1435}
1436
1437template <class... Types>
1438NumericVariable *FileCheckPatternContext::makeNumericVariable(Types... args) {
1439 NumericVariables.push_back(std::make_unique<NumericVariable>(args...));
1440 return NumericVariables.back().get();
1441}
1442
1444FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
1445 size_t InsertIdx) {
1446 Substitutions.push_back(
1447 std::make_unique<StringSubstitution>(this, VarName, InsertIdx));
1448 return Substitutions.back().get();
1449}
1450
1451Substitution *FileCheckPatternContext::makeNumericSubstitution(
1452 StringRef ExpressionStr, std::unique_ptr<Expression> Expression,
1453 size_t InsertIdx) {
1454 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1455 this, ExpressionStr, std::move(Expression), InsertIdx));
1456 return Substitutions.back().get();
1457}
1458
1459size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
1460 // Offset keeps track of the current offset within the input Str
1461 size_t Offset = 0;
1462 // [...] Nesting depth
1463 size_t BracketDepth = 0;
1464
1465 while (!Str.empty()) {
1466 if (Str.starts_with("]]") && BracketDepth == 0)
1467 return Offset;
1468 if (Str[0] == '\\') {
1469 // Backslash escapes the next char within regexes, so skip them both.
1470 Str = Str.substr(2);
1471 Offset += 2;
1472 } else {
1473 switch (Str[0]) {
1474 default:
1475 break;
1476 case '[':
1477 BracketDepth++;
1478 break;
1479 case ']':
1480 if (BracketDepth == 0) {
1481 SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
1483 "missing closing \"]\" for regex variable");
1484 exit(1);
1485 }
1486 BracketDepth--;
1487 break;
1488 }
1489 Str = Str.substr(1);
1490 Offset++;
1491 }
1492 }
1493
1494 return StringRef::npos;
1495}
1496
1499 OutputBuffer.reserve(MB.getBufferSize());
1500
1501 for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
1502 Ptr != End; ++Ptr) {
1503 // Eliminate trailing dosish \r.
1504 if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
1505 continue;
1506 }
1507
1508 // If current char is not a horizontal whitespace or if horizontal
1509 // whitespace canonicalization is disabled, dump it to output as is.
1510 if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
1511 OutputBuffer.push_back(*Ptr);
1512 continue;
1513 }
1514
1515 // Otherwise, add one space and advance over neighboring space.
1516 OutputBuffer.push_back(' ');
1517 while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
1518 ++Ptr;
1519 }
1520
1521 // Add a null byte and then return all but that byte.
1522 OutputBuffer.push_back('\0');
1523 return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
1524}
1525
1526static bool IsPartOfWord(char c) {
1527 return (isAlnum(c) || c == '-' || c == '_');
1528}
1529
1531 assert(Count > 0 && "zero and negative counts are not supported");
1532 assert((C == 1 || Kind == CheckPlain) &&
1533 "count supported only for plain CHECK directives");
1534 Count = C;
1535 return *this;
1536}
1537
1539 if (Modifiers.none())
1540 return "";
1541 std::string Ret;
1542 raw_string_ostream OS(Ret);
1543 OS << '{';
1544 if (isLiteralMatch())
1545 OS << "LITERAL";
1546 OS << '}';
1547 return Ret;
1548}
1549
1551 // Append directive modifiers.
1552 auto WithModifiers = [this, Prefix](StringRef Str) -> std::string {
1553 return (Prefix + Str + getModifiersDescription()).str();
1554 };
1555
1556 switch (Kind) {
1557 case Check::CheckNone:
1558 return "invalid";
1560 return "misspelled";
1561 case Check::CheckPlain:
1562 if (Count > 1)
1563 return WithModifiers("-COUNT");
1564 return WithModifiers("");
1565 case Check::CheckNext:
1566 return WithModifiers("-NEXT");
1567 case Check::CheckSame:
1568 return WithModifiers("-SAME");
1569 case Check::CheckNot:
1570 return WithModifiers("-NOT");
1571 case Check::CheckDAG:
1572 return WithModifiers("-DAG");
1573 case Check::CheckLabel:
1574 return WithModifiers("-LABEL");
1575 case Check::CheckEmpty:
1576 return WithModifiers("-EMPTY");
1578 return std::string(Prefix);
1579 case Check::CheckEOF:
1580 return "implicit EOF";
1581 case Check::CheckBadNot:
1582 return "bad NOT";
1584 return "bad COUNT";
1585 }
1586 llvm_unreachable("unknown FileCheckType");
1587}
1588
1589static std::pair<Check::FileCheckType, StringRef>
1591 bool &Misspelled) {
1592 if (Buffer.size() <= Prefix.size())
1593 return {Check::CheckNone, StringRef()};
1594
1595 StringRef Rest = Buffer.drop_front(Prefix.size());
1596 // Check for comment.
1597 if (llvm::is_contained(Req.CommentPrefixes, Prefix)) {
1598 if (Rest.consume_front(":"))
1599 return {Check::CheckComment, Rest};
1600 // Ignore a comment prefix if it has a suffix like "-NOT".
1601 return {Check::CheckNone, StringRef()};
1602 }
1603
1604 auto ConsumeModifiers = [&](Check::FileCheckType Ret)
1605 -> std::pair<Check::FileCheckType, StringRef> {
1606 if (Rest.consume_front(":"))
1607 return {Ret, Rest};
1608 if (!Rest.consume_front("{"))
1609 return {Check::CheckNone, StringRef()};
1610
1611 // Parse the modifiers, speparated by commas.
1612 do {
1613 // Allow whitespace in modifiers list.
1614 Rest = Rest.ltrim();
1615 if (Rest.consume_front("LITERAL"))
1616 Ret.setLiteralMatch();
1617 else
1618 return {Check::CheckNone, Rest};
1619 // Allow whitespace in modifiers list.
1620 Rest = Rest.ltrim();
1621 } while (Rest.consume_front(","));
1622 if (!Rest.consume_front("}:"))
1623 return {Check::CheckNone, Rest};
1624 return {Ret, Rest};
1625 };
1626
1627 // Verify that the prefix is followed by directive modifiers or a colon.
1628 if (Rest.consume_front(":"))
1629 return {Check::CheckPlain, Rest};
1630 if (Rest.front() == '{')
1631 return ConsumeModifiers(Check::CheckPlain);
1632
1633 if (Rest.consume_front("_"))
1634 Misspelled = true;
1635 else if (!Rest.consume_front("-"))
1636 return {Check::CheckNone, StringRef()};
1637
1638 if (Rest.consume_front("COUNT-")) {
1639 int64_t Count;
1640 if (Rest.consumeInteger(10, Count))
1641 // Error happened in parsing integer.
1642 return {Check::CheckBadCount, Rest};
1643 if (Count <= 0 || Count > INT32_MAX)
1644 return {Check::CheckBadCount, Rest};
1645 if (Rest.front() != ':' && Rest.front() != '{')
1646 return {Check::CheckBadCount, Rest};
1647 return ConsumeModifiers(
1649 }
1650
1651 // You can't combine -NOT with another suffix.
1652 if (Rest.starts_with("DAG-NOT:") || Rest.starts_with("NOT-DAG:") ||
1653 Rest.starts_with("NEXT-NOT:") || Rest.starts_with("NOT-NEXT:") ||
1654 Rest.starts_with("SAME-NOT:") || Rest.starts_with("NOT-SAME:") ||
1655 Rest.starts_with("EMPTY-NOT:") || Rest.starts_with("NOT-EMPTY:"))
1656 return {Check::CheckBadNot, Rest};
1657
1658 if (Rest.consume_front("NEXT"))
1659 return ConsumeModifiers(Check::CheckNext);
1660
1661 if (Rest.consume_front("SAME"))
1662 return ConsumeModifiers(Check::CheckSame);
1663
1664 if (Rest.consume_front("NOT"))
1665 return ConsumeModifiers(Check::CheckNot);
1666
1667 if (Rest.consume_front("DAG"))
1668 return ConsumeModifiers(Check::CheckDAG);
1669
1670 if (Rest.consume_front("LABEL"))
1671 return ConsumeModifiers(Check::CheckLabel);
1672
1673 if (Rest.consume_front("EMPTY"))
1674 return ConsumeModifiers(Check::CheckEmpty);
1675
1676 return {Check::CheckNone, Rest};
1677}
1678
1679static std::pair<Check::FileCheckType, StringRef>
1681 bool Misspelled = false;
1682 auto Res = FindCheckType(Req, Buffer, Prefix, Misspelled);
1683 if (Res.first != Check::CheckNone && Misspelled)
1684 return {Check::CheckMisspelled, Res.second};
1685 return Res;
1686}
1687
1688// From the given position, find the next character after the word.
1689static size_t SkipWord(StringRef Str, size_t Loc) {
1690 while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
1691 ++Loc;
1692 return Loc;
1693}
1694
1695static const char *DefaultCheckPrefixes[] = {"CHECK"};
1696static const char *DefaultCommentPrefixes[] = {"COM", "RUN"};
1697
1699 if (Req.CheckPrefixes.empty()) {
1701 Req.IsDefaultCheckPrefix = true;
1702 }
1703 if (Req.CommentPrefixes.empty())
1705}
1706
1708 /// Prefixes and their first occurrence past the current position.
1711
1713 ArrayRef<StringRef> CommentPrefixes, StringRef Input)
1714 : Input(Input) {
1715 for (StringRef Prefix : CheckPrefixes)
1716 Prefixes.push_back({Prefix, Input.find(Prefix)});
1717 for (StringRef Prefix : CommentPrefixes)
1718 Prefixes.push_back({Prefix, Input.find(Prefix)});
1719
1720 // Sort by descending length.
1722 [](auto A, auto B) { return A.first.size() > B.first.size(); });
1723 }
1724
1725 /// Find the next match of a prefix in Buffer.
1726 /// Returns empty StringRef if not found.
1728 assert(Buffer.data() >= Input.data() &&
1729 Buffer.data() + Buffer.size() == Input.data() + Input.size() &&
1730 "Buffer must be suffix of Input");
1731
1732 size_t From = Buffer.data() - Input.data();
1733 StringRef Match;
1734 for (auto &[Prefix, Pos] : Prefixes) {
1735 // If the last occurrence was before From, find the next one after From.
1736 if (Pos < From)
1737 Pos = Input.find(Prefix, From);
1738 // Find the first prefix with the lowest position.
1739 if (Pos != StringRef::npos &&
1740 (Match.empty() || size_t(Match.data() - Input.data()) > Pos))
1741 Match = StringRef(Input.substr(Pos, Prefix.size()));
1742 }
1743 return Match;
1744 }
1745};
1746
1747/// Searches the buffer for the first prefix in the prefix regular expression.
1748///
1749/// This searches the buffer using the provided regular expression, however it
1750/// enforces constraints beyond that:
1751/// 1) The found prefix must not be a suffix of something that looks like
1752/// a valid prefix.
1753/// 2) The found prefix must be followed by a valid check type suffix using \c
1754/// FindCheckType above.
1755///
1756/// \returns a pair of StringRefs into the Buffer, which combines:
1757/// - the first match of the regular expression to satisfy these two is
1758/// returned,
1759/// otherwise an empty StringRef is returned to indicate failure.
1760/// - buffer rewound to the location right after parsed suffix, for parsing
1761/// to continue from
1762///
1763/// If this routine returns a valid prefix, it will also shrink \p Buffer to
1764/// start at the beginning of the returned prefix, increment \p LineNumber for
1765/// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1766/// check found by examining the suffix.
1767///
1768/// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1769/// is unspecified.
1770static std::pair<StringRef, StringRef>
1772 StringRef &Buffer, unsigned &LineNumber,
1773 Check::FileCheckType &CheckTy) {
1774 while (!Buffer.empty()) {
1775 // Find the first (longest) prefix match.
1776 StringRef Prefix = Matcher.match(Buffer);
1777 if (Prefix.empty())
1778 // No match at all, bail.
1779 return {StringRef(), StringRef()};
1780
1781 assert(Prefix.data() >= Buffer.data() &&
1782 Prefix.data() < Buffer.data() + Buffer.size() &&
1783 "Prefix doesn't start inside of buffer!");
1784 size_t Loc = Prefix.data() - Buffer.data();
1785 StringRef Skipped = Buffer.substr(0, Loc);
1786 Buffer = Buffer.drop_front(Loc);
1787 LineNumber += Skipped.count('\n');
1788
1789 // Check that the matched prefix isn't a suffix of some other check-like
1790 // word.
1791 // FIXME: This is a very ad-hoc check. it would be better handled in some
1792 // other way. Among other things it seems hard to distinguish between
1793 // intentional and unintentional uses of this feature.
1794 if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
1795 // Now extract the type.
1796 StringRef AfterSuffix;
1797 std::tie(CheckTy, AfterSuffix) = FindCheckType(Req, Buffer, Prefix);
1798
1799 // If we've found a valid check type for this prefix, we're done.
1800 if (CheckTy != Check::CheckNone)
1801 return {Prefix, AfterSuffix};
1802 }
1803
1804 // If we didn't successfully find a prefix, we need to skip this invalid
1805 // prefix and continue scanning. We directly skip the prefix that was
1806 // matched and any additional parts of that check-like word.
1807 Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
1808 }
1809
1810 // We ran out of buffer while skipping partial matches so give up.
1811 return {StringRef(), StringRef()};
1812}
1813
1815 assert(!LineVariable && "@LINE pseudo numeric variable already created");
1816 StringRef LineName = "@LINE";
1817 LineVariable = makeNumericVariable(
1819 GlobalNumericVariableTable[LineName] = LineVariable;
1820}
1821
1823 : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()) {}
1824
1825FileCheck::~FileCheck() = default;
1826
1828 SourceMgr &SM, StringRef Buffer,
1829 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1830 if (ImpPatBufferIDRange)
1831 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1832
1833 Error DefineError =
1834 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1835 if (DefineError) {
1836 logAllUnhandledErrors(std::move(DefineError), errs());
1837 return true;
1838 }
1839
1840 PatternContext->createLineVariable();
1841
1842 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1843 for (StringRef PatternString : Req.ImplicitCheckNot) {
1844 // Create a buffer with fake command line content in order to display the
1845 // command line option responsible for the specific implicit CHECK-NOT.
1846 std::string Prefix = "-implicit-check-not='";
1847 std::string Suffix = "'";
1848 std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
1849 (Prefix + PatternString + Suffix).str(), "command line");
1850
1851 StringRef PatternInBuffer =
1852 CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
1853 unsigned BufferID = SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
1854 if (ImpPatBufferIDRange) {
1855 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1856 ImpPatBufferIDRange->first = BufferID;
1857 ImpPatBufferIDRange->second = BufferID + 1;
1858 } else {
1859 assert(BufferID == ImpPatBufferIDRange->second &&
1860 "expected consecutive source buffer IDs");
1861 ++ImpPatBufferIDRange->second;
1862 }
1863 }
1864
1865 ImplicitNegativeChecks.emplace_back(
1866 Pattern(Check::CheckNot, PatternContext.get()),
1867 StringRef("IMPLICIT-CHECK"));
1868 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1869 PatternInBuffer, "IMPLICIT-CHECK", SM, Req);
1870 }
1871
1872 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1873 ImplicitNegativeChecks;
1874 // LineNumber keeps track of the line on which CheckPrefix instances are
1875 // found.
1876 unsigned LineNumber = 1;
1877
1878 addDefaultPrefixes(Req);
1879 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1880 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1881 Req.CheckPrefixes.end());
1882 const size_t DistinctPrefixes = PrefixesNotFound.size();
1883 while (true) {
1884 Check::FileCheckType CheckTy;
1885
1886 // See if a prefix occurs in the memory buffer.
1887 StringRef UsedPrefix;
1888 StringRef AfterSuffix;
1889 std::tie(UsedPrefix, AfterSuffix) =
1890 FindFirstMatchingPrefix(Req, Matcher, Buffer, LineNumber, CheckTy);
1891 if (UsedPrefix.empty())
1892 break;
1893 if (CheckTy != Check::CheckComment)
1894 PrefixesNotFound.erase(UsedPrefix);
1895
1896 assert(UsedPrefix.data() == Buffer.data() &&
1897 "Failed to move Buffer's start forward, or pointed prefix outside "
1898 "of the buffer!");
1899
1900 [[maybe_unused]] const char *BufferEnd = Buffer.data() + Buffer.size();
1901 assert(AfterSuffix.data() >= Buffer.data() &&
1902 AfterSuffix.data() <= BufferEnd &&
1903 "Parsing after suffix doesn't start inside of buffer!");
1904
1905 // Skip the buffer to the end of the parsed directive suffix.
1906 Buffer = AfterSuffix;
1907
1908 // Location to use for error messages.
1909 const char *UsedPrefixStart = UsedPrefix.data();
1910
1911 // Complain about misspelled directives.
1912 if (CheckTy == Check::CheckMisspelled) {
1913 StringRef UsedDirective(UsedPrefix.data(),
1914 AfterSuffix.data() - UsedPrefix.data());
1915 SM.PrintMessage(SMLoc::getFromPointer(UsedDirective.data()),
1917 "misspelled directive '" + UsedDirective + "'");
1918 return true;
1919 }
1920
1921 // Complain about useful-looking but unsupported suffixes.
1922 if (CheckTy == Check::CheckBadNot) {
1924 "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
1925 return true;
1926 }
1927
1928 // Complain about invalid count specification.
1929 if (CheckTy == Check::CheckBadCount) {
1931 "invalid count in -COUNT specification on prefix '" +
1932 UsedPrefix + "'");
1933 return true;
1934 }
1935
1936 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1937 // leading whitespace.
1938 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1939 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
1940
1941 // Scan ahead to the end of line.
1942 size_t EOL = Buffer.find_first_of("\n\r");
1943
1944 // Remember the location of the start of the pattern, for diagnostics.
1945 SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
1946
1947 // Extract the pattern from the buffer.
1948 StringRef PatternBuffer = Buffer.substr(0, EOL);
1949 Buffer = Buffer.substr(EOL);
1950
1951 // If this is a comment, we're done.
1952 if (CheckTy == Check::CheckComment)
1953 continue;
1954
1955 // Parse the pattern.
1956 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1957 if (P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1958 return true;
1959
1960 // Verify that CHECK-LABEL lines do not define or use variables
1961 if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
1962 SM.PrintMessage(
1964 "found '" + UsedPrefix + "-LABEL:'"
1965 " with variable definition or use");
1966 return true;
1967 }
1968
1969 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1970 if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
1971 CheckTy == Check::CheckEmpty) &&
1972 CheckStrings.empty()) {
1973 StringRef Type = CheckTy == Check::CheckNext
1974 ? "NEXT"
1975 : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
1976 SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
1978 "found '" + UsedPrefix + "-" + Type +
1979 "' without previous '" + UsedPrefix + ": line");
1980 return true;
1981 }
1982
1983 // Handle CHECK-DAG/-NOT.
1984 if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
1985 DagNotMatches.emplace_back(P, UsedPrefix);
1986 continue;
1987 }
1988
1989 // Okay, add the string we captured to the output vector and move on.
1990 CheckStrings.emplace_back(std::move(P), UsedPrefix, PatternLoc,
1991 std::move(DagNotMatches));
1992 DagNotMatches = ImplicitNegativeChecks;
1993 }
1994
1995 // When there are no used prefixes we report an error except in the case that
1996 // no prefix is specified explicitly but -implicit-check-not is specified.
1997 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1998 const bool SomePrefixesUnexpectedlyNotUsed =
1999 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
2000 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
2001 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
2002 errs() << "error: no check strings found with prefix"
2003 << (PrefixesNotFound.size() > 1 ? "es " : " ");
2004 ListSeparator LS;
2005 for (StringRef MissingPrefix : PrefixesNotFound)
2006 errs() << LS << "\'" << MissingPrefix << ":'";
2007 errs() << '\n';
2008 return true;
2009 }
2010
2011 // Add an EOF pattern for any trailing --implicit-check-not/CHECK-DAG/-NOTs,
2012 // and use the first prefix as a filler for the error message.
2013 if (!DagNotMatches.empty()) {
2014 CheckStrings.emplace_back(
2015 Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
2016 *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()),
2017 std::move(DagNotMatches));
2018 }
2019
2020 return false;
2021}
2022
2023/// Returns either (1) \c ErrorSuccess if there was no error or (2)
2024/// \c ErrorReported if an error was reported, such as an unexpected match.
2025static Error printMatch(bool ExpectedMatch, const SourceMgr &SM,
2026 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2027 int MatchedCount, StringRef Buffer,
2028 Pattern::MatchResult MatchResult,
2029 const FileCheckRequest &Req, FileCheckDiagList *Diags) {
2030 // Suppress some verbosity if there's no error.
2031 bool HasError = !ExpectedMatch || MatchResult.TheError;
2032 bool PrintDiag = true;
2033 if (!HasError) {
2034 if (!Req.Verbose)
2035 return ErrorReported::reportedOrSuccess(HasError);
2036 if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
2037 return ErrorReported::reportedOrSuccess(HasError);
2038 // Due to their verbosity, we don't print verbose diagnostics here if we're
2039 // gathering them for Diags to be rendered elsewhere, but we always print
2040 // other diagnostics.
2041 PrintDiag = !Diags;
2042 }
2043
2044 // Add "found" diagnostic, substitutions, and variable definitions to Diags.
2047 SMRange MatchRange = buildMatchRange(Buffer, MatchResult.TheMatch->Pos,
2048 MatchResult.TheMatch->Len);
2049 SMRange SearchRange = buildSearchRange(Buffer);
2050 if (Diags) {
2051 Diags->emplace<MatchFoundDiag>(Pat.getCheckTy(), Loc, Status, MatchRange,
2052 SearchRange);
2053 Pat.printSubstitutions(SM, Buffer, MatchRange, Diags);
2054 Pat.printVariableDefs(SM, Diags);
2055 }
2056 if (!PrintDiag) {
2057 assert(!HasError && "expected to report more diagnostics for error");
2058 return ErrorReported::reportedOrSuccess(HasError);
2059 }
2060
2061 // Print the match.
2062 std::string Message = formatv("{0}: {1} string found in input",
2063 Pat.getCheckTy().getDescription(Prefix),
2064 (ExpectedMatch ? "expected" : "excluded"))
2065 .str();
2066 if (Pat.getCount() > 1)
2067 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2068 SM.PrintMessage(
2069 Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
2070 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
2071 {MatchRange});
2072
2073 // Print additional information, which can be useful even if there are errors.
2074 Pat.printSubstitutions(SM, Buffer, MatchRange, nullptr);
2075 Pat.printVariableDefs(SM, nullptr);
2076
2077 // Print errors and add them to Diags. We report these errors after the match
2078 // itself because we found them after the match. If we had found them before
2079 // the match, we'd be in printNoMatch.
2080 handleAllErrors(std::move(MatchResult.TheError),
2081 [&](const ErrorDiagnostic &E) {
2082 E.log(errs());
2083 if (Diags) {
2084 Diags->emplace<MatchCustomNoteDiag>(E.getRange(),
2085 E.getMessage().str(),
2086 /*AddsError=*/true);
2087 }
2088 });
2089 return ErrorReported::reportedOrSuccess(HasError);
2090}
2091
2092/// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2093/// \c ErrorReported if an error was reported, such as an expected match not
2094/// found.
2095static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM,
2096 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2097 int MatchedCount, StringRef Buffer, Error MatchError,
2098 bool VerboseVerbose, FileCheckDiagList *Diags) {
2099 // Print any pattern errors, and record them to be added to Diags later.
2100 bool HasError = ExpectedMatch;
2101 bool HasPatternError = false;
2106 std::move(MatchError),
2107 [&](const ErrorDiagnostic &E) {
2108 HasError = HasPatternError = true;
2110 E.log(errs());
2111 if (Diags)
2112 ErrorMsgs.push_back(E.getMessage().str());
2113 },
2114 // NotFoundError is why printNoMatch was invoked.
2115 [](const NotFoundError &E) {});
2116
2117 // Suppress some verbosity if there's no error.
2118 bool PrintDiag = true;
2119 if (!HasError) {
2120 if (!VerboseVerbose)
2121 return ErrorReported::reportedOrSuccess(HasError);
2122 // Due to their verbosity, we don't print verbose diagnostics here if we're
2123 // gathering them for Diags to be rendered elsewhere, but we always print
2124 // other diagnostics.
2125 PrintDiag = !Diags;
2126 }
2127
2128 // Add "not found" diagnostic, substitutions, and pattern errors to Diags.
2129 //
2130 // We handle Diags a little differently than the errors we print directly:
2131 // we add the "not found" diagnostic to Diags even if there are pattern
2132 // errors. The reason is that we need to attach pattern errors as notes
2133 // somewhere in the input, and the input search range from the "not found"
2134 // diagnostic is all we have to anchor them.
2135 SMRange SearchRange = buildSearchRange(Buffer);
2136 if (Diags) {
2137 Diags->emplace<MatchNoneDiag>(Pat.getCheckTy(), Loc, Status, SearchRange);
2138 for (StringRef ErrorMsg : ErrorMsgs)
2139 Diags->emplace<MatchCustomNoteDiag>(ErrorMsg);
2140 Pat.printSubstitutions(SM, Buffer, SearchRange, Diags);
2141 Pat.printVariableDefAttempts(SM, Buffer, Diags);
2142 }
2143 if (!PrintDiag) {
2144 assert(!HasError && "expected to report more diagnostics for error");
2145 return ErrorReported::reportedOrSuccess(HasError);
2146 }
2147
2148 // Print "not found" diagnostic, except that's implied if we already printed a
2149 // pattern error.
2150 if (!HasPatternError) {
2151 std::string Message = formatv("{0}: {1} string not found in input",
2152 Pat.getCheckTy().getDescription(Prefix),
2153 (ExpectedMatch ? "expected" : "excluded"))
2154 .str();
2155 if (Pat.getCount() > 1)
2156 Message +=
2157 formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2158 SM.PrintMessage(Loc,
2159 ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark,
2160 Message);
2161 SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note,
2162 "scanning from here");
2163 }
2164
2165 // Print additional information, which can be useful even after a pattern
2166 // error.
2167 Pat.printSubstitutions(SM, Buffer, SearchRange, nullptr);
2168 Pat.printVariableDefAttempts(SM, Buffer, nullptr);
2169
2170 if (ExpectedMatch)
2171 Pat.printFuzzyMatch(SM, Buffer, Diags);
2172 return ErrorReported::reportedOrSuccess(HasError);
2173}
2174
2175/// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2176/// \c ErrorReported if an error was reported.
2177static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM,
2178 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2179 int MatchedCount, StringRef Buffer,
2180 Pattern::MatchResult MatchResult,
2181 const FileCheckRequest &Req,
2182 FileCheckDiagList *Diags) {
2183 if (MatchResult.TheMatch)
2184 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2185 std::move(MatchResult), Req, Diags);
2186 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2187 std::move(MatchResult.TheError), Req.VerboseVerbose,
2188 Diags);
2189}
2190
2191/// Counts the number of newlines in the specified range.
2193 const char *&FirstNewLine) {
2194 unsigned NumNewLines = 0;
2195 while (true) {
2196 // Scan for newline.
2197 Range = Range.substr(Range.find_first_of("\n\r"));
2198 if (Range.empty())
2199 return NumNewLines;
2200
2201 ++NumNewLines;
2202
2203 // Handle \n\r and \r\n as a single newline.
2204 if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
2205 (Range[0] != Range[1]))
2206 Range = Range.substr(1);
2207 Range = Range.substr(1);
2208
2209 if (NumNewLines == 1)
2210 FirstNewLine = Range.begin();
2211 }
2212}
2213
2215 bool IsLabelScanMode, size_t &MatchLen,
2216 FileCheckRequest &Req,
2217 FileCheckDiagList *Diags) const {
2218 size_t LastPos = 0;
2219 std::vector<const DagNotPrefixInfo *> NotStrings;
2220
2221 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
2222 // bounds; we have not processed variable definitions within the bounded block
2223 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
2224 // over the block again (including the last CHECK-LABEL) in normal mode.
2225 if (!IsLabelScanMode) {
2226 // Match "dag strings" (with mixed "not strings" if any).
2227 LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
2228 if (LastPos == StringRef::npos)
2229 return StringRef::npos;
2230 }
2231
2232 // Match itself from the last position after matching CHECK-DAG.
2233 size_t LastMatchEnd = LastPos;
2234 size_t FirstMatchPos = 0;
2235 // Go match the pattern Count times. Majority of patterns only match with
2236 // count 1 though.
2237 assert(Pat.getCount() != 0 && "pattern count can not be zero");
2238 for (int i = 1; i <= Pat.getCount(); i++) {
2239 StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
2240 // get a match at current start point
2241 Pattern::MatchResult MatchResult = Pat.match(MatchBuffer, SM);
2242
2243 // report
2244 if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, Prefix, Loc,
2245 Pat, i, MatchBuffer,
2246 std::move(MatchResult), Req, Diags)) {
2247 cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2248 return StringRef::npos;
2249 }
2250
2251 size_t MatchPos = MatchResult.TheMatch->Pos;
2252 if (i == 1)
2253 FirstMatchPos = LastPos + MatchPos;
2254
2255 // move start point after the match
2256 LastMatchEnd += MatchPos + MatchResult.TheMatch->Len;
2257 }
2258 // Full match len counts from first match pos.
2259 MatchLen = LastMatchEnd - FirstMatchPos;
2260
2261 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
2262 // or CHECK-NOT
2263 if (!IsLabelScanMode) {
2264 size_t MatchPos = FirstMatchPos - LastPos;
2265 StringRef MatchBuffer = Buffer.substr(LastPos);
2266 StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
2267
2268 // If this check is a "CHECK-NEXT", verify that the previous match was on
2269 // the previous line (i.e. that there is one newline between them).
2270 if (CheckNext(SM, SkippedRegion)) {
2271 if (Diags) {
2272 if (Req.Verbose) {
2274 } else {
2275 Diags->emplace<MatchFoundDiag>(
2276 Pat.getCheckTy(), Loc, MatchFoundDiag::WrongLine,
2277 buildMatchRange(MatchBuffer, MatchPos, MatchLen),
2278 buildSearchRange(MatchBuffer));
2279 }
2280 }
2281 return StringRef::npos;
2282 }
2283
2284 // If this check is a "CHECK-SAME", verify that the previous match was on
2285 // the same line (i.e. that there is no newline between them).
2286 if (CheckSame(SM, SkippedRegion)) {
2287 if (Diags) {
2288 if (Req.Verbose) {
2290 } else {
2291 Diags->emplace<MatchFoundDiag>(
2292 Pat.getCheckTy(), Loc, MatchFoundDiag::WrongLine,
2293 buildMatchRange(MatchBuffer, MatchPos, MatchLen),
2294 buildSearchRange(MatchBuffer));
2295 }
2296 }
2297 return StringRef::npos;
2298 }
2299
2300 // If this match had "not strings", verify that they don't exist in the
2301 // skipped region.
2302 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2303 return StringRef::npos;
2304 }
2305
2306 return FirstMatchPos;
2307}
2308
2309bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
2310 if (Pat.getCheckTy() != Check::CheckNext &&
2311 Pat.getCheckTy() != Check::CheckEmpty)
2312 return false;
2313
2314 Twine CheckName =
2315 Prefix +
2316 Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
2317
2318 // Count the number of newlines between the previous match and this one.
2319 const char *FirstNewLine = nullptr;
2320 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
2321
2322 if (NumNewLines == 0) {
2324 CheckName + ": is on the same line as previous match");
2326 "'next' match was here");
2328 "previous match ended here");
2329 return true;
2330 }
2331
2332 if (NumNewLines != 1) {
2334 CheckName +
2335 ": is not on the line after the previous match");
2337 "'next' match was here");
2339 "previous match ended here");
2341 "non-matching line after previous match is here");
2342 return true;
2343 }
2344
2345 return false;
2346}
2347
2348bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
2349 if (Pat.getCheckTy() != Check::CheckSame)
2350 return false;
2351
2352 // Count the number of newlines between the previous match and this one.
2353 const char *FirstNewLine = nullptr;
2354 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
2355
2356 if (NumNewLines != 0) {
2358 Prefix +
2359 "-SAME: is not on the same line as the previous match");
2361 "'next' match was here");
2363 "previous match ended here");
2364 return true;
2365 }
2366
2367 return false;
2368}
2369
2371 const SourceMgr &SM, StringRef Buffer,
2372 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2373 const FileCheckRequest &Req, FileCheckDiagList *Diags) const {
2374 bool DirectiveFail = false;
2375 for (auto NotInfo : NotStrings) {
2376 assert((NotInfo->DagNotPat.getCheckTy() == Check::CheckNot) &&
2377 "Expect CHECK-NOT!");
2378 Pattern::MatchResult MatchResult = NotInfo->DagNotPat.match(Buffer, SM);
2379 if (Error Err = reportMatchResult(
2380 /*ExpectedMatch=*/false, SM, NotInfo->DagNotPrefix,
2381 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2382 std::move(MatchResult), Req, Diags)) {
2383 cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2384 DirectiveFail = true;
2385 continue;
2386 }
2387 }
2388 return DirectiveFail;
2389}
2390
2391size_t
2393 std::vector<const DagNotPrefixInfo *> &NotStrings,
2394 const FileCheckRequest &Req,
2395 FileCheckDiagList *Diags) const {
2396 if (DagNotStrings.empty())
2397 return 0;
2398
2399 // The start of the search range.
2400 size_t StartPos = 0;
2401
2402 struct MatchRange {
2403 size_t Pos;
2404 size_t End;
2405 };
2406 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
2407 // ranges are erased from this list once they are no longer in the search
2408 // range.
2409 std::list<MatchRange> MatchRanges;
2410
2411 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
2412 // group, so we don't use a range-based for loop here.
2413 for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
2414 PatItr != PatEnd; ++PatItr) {
2415 const Pattern &Pat = PatItr->DagNotPat;
2416 const StringRef DNPrefix = PatItr->DagNotPrefix;
2417 assert((Pat.getCheckTy() == Check::CheckDAG ||
2418 Pat.getCheckTy() == Check::CheckNot) &&
2419 "Invalid CHECK-DAG or CHECK-NOT!");
2420
2421 if (Pat.getCheckTy() == Check::CheckNot) {
2422 NotStrings.push_back(&*PatItr);
2423 continue;
2424 }
2425
2426 assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
2427
2428 // CHECK-DAG always matches from the start.
2429 size_t MatchLen = 0, MatchPos = StartPos;
2430
2431 // Search for a match that doesn't overlap a previous match in this
2432 // CHECK-DAG group.
2433 for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
2434 StringRef MatchBuffer = Buffer.substr(MatchPos);
2435 Pattern::MatchResult MatchResult = Pat.match(MatchBuffer, SM);
2436 // With a group of CHECK-DAGs, a single mismatching means the match on
2437 // that group of CHECK-DAGs fails immediately.
2438 if (MatchResult.TheError || Req.VerboseVerbose) {
2439 if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, DNPrefix,
2440 Pat.getLoc(), Pat, 1, MatchBuffer,
2441 std::move(MatchResult), Req, Diags)) {
2442 cantFail(
2443 handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2444 return StringRef::npos;
2445 }
2446 }
2447 MatchLen = MatchResult.TheMatch->Len;
2448 // Re-calc it as the offset relative to the start of the original
2449 // string.
2450 MatchPos += MatchResult.TheMatch->Pos;
2451 MatchRange M{MatchPos, MatchPos + MatchLen};
2452 if (Req.AllowDeprecatedDagOverlap) {
2453 // We don't need to track all matches in this mode, so we just maintain
2454 // one match range that encompasses the current CHECK-DAG group's
2455 // matches.
2456 if (MatchRanges.empty())
2457 MatchRanges.insert(MatchRanges.end(), M);
2458 else {
2459 auto Block = MatchRanges.begin();
2460 Block->Pos = std::min(Block->Pos, M.Pos);
2461 Block->End = std::max(Block->End, M.End);
2462 }
2463 break;
2464 }
2465 // Iterate previous matches until overlapping match or insertion point.
2466 bool Overlap = false;
2467 for (; MI != ME; ++MI) {
2468 if (M.Pos < MI->End) {
2469 // !Overlap => New match has no overlap and is before this old match.
2470 // Overlap => New match overlaps this old match.
2471 Overlap = MI->Pos < M.End;
2472 break;
2473 }
2474 }
2475 if (!Overlap) {
2476 // Insert non-overlapping match into list.
2477 MatchRanges.insert(MI, M);
2478 break;
2479 }
2480 if (Req.VerboseVerbose) {
2481 // Due to their verbosity, we don't print verbose diagnostics here if
2482 // we're gathering them for a different rendering, but we always print
2483 // other diagnostics.
2484 if (Diags) {
2486 } else {
2487 SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
2488 SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
2489 SMRange OldRange(OldStart, OldEnd);
2490 SM.PrintMessage(OldStart, SourceMgr::DK_Note,
2491 "match discarded, overlaps earlier DAG match here",
2492 {OldRange});
2493 }
2494 }
2495 MatchPos = MI->End;
2496 }
2497 if (!Req.VerboseVerbose)
2499 /*ExpectedMatch=*/true, SM, DNPrefix, Pat.getLoc(), Pat, 1, Buffer,
2500 Pattern::MatchResult(MatchPos, MatchLen, Error::success()), Req,
2501 Diags));
2502
2503 // Handle the end of a CHECK-DAG group.
2504 if (std::next(PatItr) == PatEnd ||
2505 std::next(PatItr)->DagNotPat.getCheckTy() == Check::CheckNot) {
2506 if (!NotStrings.empty()) {
2507 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
2508 // CHECK-DAG, verify that there are no 'not' strings occurred in that
2509 // region.
2510 StringRef SkippedRegion =
2511 Buffer.slice(StartPos, MatchRanges.begin()->Pos);
2512 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2513 return StringRef::npos;
2514 // Clear "not strings".
2515 NotStrings.clear();
2516 }
2517 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
2518 // end of this CHECK-DAG group's match range.
2519 StartPos = MatchRanges.rbegin()->End;
2520 // Don't waste time checking for (impossible) overlaps before that.
2521 MatchRanges.clear();
2522 }
2523 }
2524
2525 return StartPos;
2526}
2527
2528static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes,
2529 ArrayRef<StringRef> SuppliedPrefixes) {
2530 for (StringRef Prefix : SuppliedPrefixes) {
2531 if (Prefix.empty()) {
2532 errs() << "error: supplied " << Kind << " prefix must not be the empty "
2533 << "string\n";
2534 return false;
2535 }
2536 static const Regex Validator("^[a-zA-Z0-9_-]*$");
2537 if (!Validator.match(Prefix)) {
2538 errs() << "error: supplied " << Kind << " prefix must start with a "
2539 << "letter and contain only alphanumeric characters, hyphens, and "
2540 << "underscores: '" << Prefix << "'\n";
2541 return false;
2542 }
2543 if (!UniquePrefixes.insert(Prefix).second) {
2544 errs() << "error: supplied " << Kind << " prefix must be unique among "
2545 << "check and comment prefixes: '" << Prefix << "'\n";
2546 return false;
2547 }
2548 }
2549 return true;
2550}
2551
2553 StringSet<> UniquePrefixes;
2554 // Add default prefixes to catch user-supplied duplicates of them below.
2555 if (Req.CheckPrefixes.empty())
2556 UniquePrefixes.insert_range(DefaultCheckPrefixes);
2557 if (Req.CommentPrefixes.empty())
2558 UniquePrefixes.insert_range(DefaultCommentPrefixes);
2559 // Do not validate the default prefixes, or diagnostics about duplicates might
2560 // incorrectly indicate that they were supplied by the user.
2561 if (!ValidatePrefixes("check", UniquePrefixes, Req.CheckPrefixes))
2562 return false;
2563 if (!ValidatePrefixes("comment", UniquePrefixes, Req.CommentPrefixes))
2564 return false;
2565 return true;
2566}
2567
2569 ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM) {
2570 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2571 "Overriding defined variable with command-line variable definitions");
2572
2573 if (CmdlineDefines.empty())
2574 return Error::success();
2575
2576 // Create a string representing the vector of command-line definitions. Each
2577 // definition is on its own line and prefixed with a definition number to
2578 // clarify which definition a given diagnostic corresponds to.
2579 unsigned I = 0;
2580 Error Errs = Error::success();
2581 std::string CmdlineDefsDiag;
2582 SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;
2583 for (StringRef CmdlineDef : CmdlineDefines) {
2584 std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
2585 size_t EqIdx = CmdlineDef.find('=');
2586 if (EqIdx == StringRef::npos) {
2587 CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2588 continue;
2589 }
2590 // Numeric variable definition.
2591 if (CmdlineDef[0] == '#') {
2592 // Append a copy of the command-line definition adapted to use the same
2593 // format as in the input file to be able to reuse
2594 // parseNumericSubstitutionBlock.
2595 CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
2596 std::string SubstitutionStr = std::string(CmdlineDef);
2597 SubstitutionStr[EqIdx] = ':';
2598 CmdlineDefsIndices.push_back(
2599 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2600 CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
2601 } else {
2602 CmdlineDefsDiag += DefPrefix;
2603 CmdlineDefsIndices.push_back(
2604 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2605 CmdlineDefsDiag += (CmdlineDef + "\n").str();
2606 }
2607 }
2608
2609 // Create a buffer with fake command line content in order to display
2610 // parsing diagnostic with location information and point to the
2611 // global definition with invalid syntax.
2612 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2613 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");
2614 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2615 SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
2616
2617 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2618 StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
2619 CmdlineDefIndices.second);
2620 if (CmdlineDef.empty()) {
2621 Errs = joinErrors(
2622 std::move(Errs),
2623 ErrorDiagnostic::get(SM, CmdlineDef,
2624 "missing equal sign in global definition"));
2625 continue;
2626 }
2627
2628 // Numeric variable definition.
2629 if (CmdlineDef[0] == '#') {
2630 // Now parse the definition both to check that the syntax is correct and
2631 // to create the necessary class instance.
2632 StringRef CmdlineDefExpr = CmdlineDef.substr(1);
2633 std::optional<NumericVariable *> DefinedNumericVariable;
2634 Expected<std::unique_ptr<Expression>> ExpressionResult =
2636 DefinedNumericVariable, false,
2637 std::nullopt, this, SM);
2638 if (!ExpressionResult) {
2639 Errs = joinErrors(std::move(Errs), ExpressionResult.takeError());
2640 continue;
2641 }
2642 std::unique_ptr<Expression> Expression = std::move(*ExpressionResult);
2643 // Now evaluate the expression whose value this variable should be set
2644 // to, since the expression of a command-line variable definition should
2645 // only use variables defined earlier on the command-line. If not, this
2646 // is an error and we report it.
2648 if (!Value) {
2649 Errs = joinErrors(std::move(Errs), Value.takeError());
2650 continue;
2651 }
2652
2653 assert(DefinedNumericVariable && "No variable defined");
2654 (*DefinedNumericVariable)->setValue(*Value);
2655
2656 // Record this variable definition.
2657 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2658 *DefinedNumericVariable;
2659 } else {
2660 // String variable definition.
2661 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
2662 StringRef CmdlineName = CmdlineNameVal.first;
2663 StringRef OrigCmdlineName = CmdlineName;
2665 Pattern::parseVariable(CmdlineName, SM);
2666 if (!ParseVarResult) {
2667 Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());
2668 continue;
2669 }
2670 // Check that CmdlineName does not denote a pseudo variable is only
2671 // composed of the parsed numeric variable. This catches cases like
2672 // "FOO+2" in a "FOO+2=10" definition.
2673 if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
2674 Errs = joinErrors(std::move(Errs),
2676 SM, OrigCmdlineName,
2677 "invalid name in string variable definition '" +
2678 OrigCmdlineName + "'"));
2679 continue;
2680 }
2681 StringRef Name = ParseVarResult->Name;
2682
2683 // Detect collisions between string and numeric variables when the former
2684 // is created later than the latter.
2685 if (GlobalNumericVariableTable.contains(Name)) {
2686 Errs = joinErrors(std::move(Errs),
2687 ErrorDiagnostic::get(SM, Name,
2688 "numeric variable with name '" +
2689 Name + "' already exists"));
2690 continue;
2691 }
2692 GlobalVariableTable.insert(CmdlineNameVal);
2693 // Mark the string variable as defined to detect collisions between
2694 // string and numeric variables in defineCmdlineVariables when the latter
2695 // is created later than the former. We cannot reuse GlobalVariableTable
2696 // for this by populating it with an empty string since we would then
2697 // lose the ability to detect the use of an undefined variable in
2698 // match().
2699 DefinedVariableTable[Name] = true;
2700 }
2701 }
2702
2703 return Errs;
2704}
2705
2707 SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;
2708 for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)
2709 if (Var.first()[0] != '$')
2710 LocalPatternVars.push_back(Var.first());
2711
2712 // Numeric substitution reads the value of a variable directly, not via
2713 // GlobalNumericVariableTable. Therefore, we clear local variables by
2714 // clearing their value which will lead to a numeric substitution failure. We
2715 // also mark the variable for removal from GlobalNumericVariableTable since
2716 // this is what defineCmdlineVariables checks to decide that no global
2717 // variable has been defined.
2718 for (const auto &Var : GlobalNumericVariableTable)
2719 if (Var.first()[0] != '$') {
2720 Var.getValue()->clearValue();
2721 LocalNumericVars.push_back(Var.first());
2722 }
2723
2724 for (const auto &Var : LocalPatternVars)
2725 GlobalVariableTable.erase(Var);
2726 for (const auto &Var : LocalNumericVars)
2727 GlobalNumericVariableTable.erase(Var);
2728}
2729
2731 FileCheckDiagList *Diags) {
2732 bool ChecksFailed = false;
2733
2734 unsigned i = 0, j = 0, e = CheckStrings.size();
2735 while (true) {
2736 StringRef CheckRegion;
2737 if (j == e) {
2738 CheckRegion = Buffer;
2739 } else {
2740 const FileCheckString &CheckLabelStr = CheckStrings[j];
2741 if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
2742 ++j;
2743 continue;
2744 }
2745
2746 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
2747 size_t MatchLabelLen = 0;
2748 size_t MatchLabelPos =
2749 CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
2750 if (MatchLabelPos == StringRef::npos)
2751 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
2752 return false;
2753
2754 CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
2755 Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
2756 ++j;
2757 }
2758
2759 // Do not clear the first region as it's the one before the first
2760 // CHECK-LABEL and it would clear variables defined on the command-line
2761 // before they get used.
2762 if (i != 0 && Req.EnableVarScope)
2763 PatternContext->clearLocalVars();
2764
2765 for (; i != j; ++i) {
2766 const FileCheckString &CheckStr = CheckStrings[i];
2767
2768 // Check each string within the scanned region, including a second check
2769 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
2770 size_t MatchLen = 0;
2771 size_t MatchPos =
2772 CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
2773
2774 if (MatchPos == StringRef::npos) {
2775 ChecksFailed = true;
2776 i = j;
2777 break;
2778 }
2779
2780 CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
2781 }
2782
2783 if (j == e)
2784 break;
2785 }
2786
2787 // Success if no checks failed.
2788 return !ChecksFailed;
2789}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
const char * Msg
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:1057
APInt abs() const
Get the absolute value.
Definition APInt.h:1815
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:325
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1966
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1992
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:1998
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1030
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:337
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition APInt.h:1134
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1979
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:2202
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:405
void emplace(ArgTys &&...Args)
Emplace a new FileCheckDiag of type DiagTy.
Definition FileCheck.h:419
void adjustPrevMatchFoundDiag(MatchFoundDiag::StatusTy Status)
Adjust the previous MatchResultDiag, which must be a MatchFoundDiag, from successful status to unsucc...
Definition FileCheck.h:434
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:354
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:331
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
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.
void printVariableDefAttempts(const SourceMgr &SM, StringRef Buffer, FileCheckDiagList *Diags) const
Prints a list of all variables that this pattern attempts to capture.
@ 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:251
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:84
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:34
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
Definition SourceMgr.h:160
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
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:736
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:597
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:635
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:720
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:826
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:838
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:606
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:850
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:661
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:642
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.
@ 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:577
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:2224
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:1762
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:1652
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
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:1963
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:878
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.