LLVM 23.0.0git
FileCheck.cpp
Go to the documentation of this file.
1//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// FileCheck does a line-by line check of a file that validates whether it
10// contains the expected content. This is useful for regression tests etc.
11//
12// This file implements most of the API that will be used by the FileCheck utility
13// as well as various unittests.
14//===----------------------------------------------------------------------===//
15
17#include "FileCheckImpl.h"
18#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/StringSet.h"
21#include "llvm/ADT/Twine.h"
23#include <cstdint>
24#include <list>
25#include <set>
26#include <tuple>
27#include <utility>
28
29using namespace llvm;
30
31constexpr static int BackrefLimit = 20;
32
34 switch (Value) {
35 case Kind::NoFormat:
36 return StringRef("<none>");
37 case Kind::Unsigned:
38 return StringRef("%u");
39 case Kind::Signed:
40 return StringRef("%d");
41 case Kind::HexUpper:
42 return StringRef("%X");
43 case Kind::HexLower:
44 return StringRef("%x");
45 }
46 llvm_unreachable("unknown expression format");
47}
48
50 StringRef AlternateFormPrefix = AlternateForm ? StringRef("0x") : StringRef();
51
52 auto CreatePrecisionRegex = [&](StringRef S) {
53 return (Twine(AlternateFormPrefix) + S + Twine('{') + Twine(Precision) +
54 "}")
55 .str();
56 };
57
58 switch (Value) {
59 case Kind::Unsigned:
60 if (Precision)
61 return CreatePrecisionRegex("([1-9][0-9]*)?[0-9]");
62 return std::string("[0-9]+");
63 case Kind::Signed:
64 if (Precision)
65 return CreatePrecisionRegex("-?([1-9][0-9]*)?[0-9]");
66 return std::string("-?[0-9]+");
67 case Kind::HexUpper:
68 if (Precision)
69 return CreatePrecisionRegex("([1-9A-F][0-9A-F]*)?[0-9A-F]");
70 return (Twine(AlternateFormPrefix) + Twine("[0-9A-F]+")).str();
71 case Kind::HexLower:
72 if (Precision)
73 return CreatePrecisionRegex("([1-9a-f][0-9a-f]*)?[0-9a-f]");
74 return (Twine(AlternateFormPrefix) + Twine("[0-9a-f]+")).str();
75 default:
76 return createStringError(std::errc::invalid_argument,
77 "trying to match value with invalid format");
78 }
79}
80
83 if (Value != Kind::Signed && IntValue.isNegative())
85
86 unsigned Radix;
87 bool UpperCase = false;
88 SmallString<8> AbsoluteValueStr;
89 StringRef SignPrefix = IntValue.isNegative() ? "-" : "";
90 switch (Value) {
91 case Kind::Unsigned:
92 case Kind::Signed:
93 Radix = 10;
94 break;
95 case Kind::HexUpper:
96 UpperCase = true;
97 Radix = 16;
98 break;
99 case Kind::HexLower:
100 Radix = 16;
101 UpperCase = false;
102 break;
103 default:
104 return createStringError(std::errc::invalid_argument,
105 "trying to match value with invalid format");
106 }
107 IntValue.abs().toString(AbsoluteValueStr, Radix, /*Signed=*/false,
108 /*formatAsCLiteral=*/false,
109 /*UpperCase=*/UpperCase);
110
111 StringRef AlternateFormPrefix = AlternateForm ? StringRef("0x") : StringRef();
112
113 if (Precision > AbsoluteValueStr.size()) {
114 unsigned LeadingZeros = Precision - AbsoluteValueStr.size();
115 return (Twine(SignPrefix) + Twine(AlternateFormPrefix) +
116 std::string(LeadingZeros, '0') + AbsoluteValueStr)
117 .str();
118 }
119
120 return (Twine(SignPrefix) + Twine(AlternateFormPrefix) + AbsoluteValueStr)
121 .str();
122}
123
124static unsigned nextAPIntBitWidth(unsigned BitWidth) {
126 : BitWidth * 2;
127}
128
129static APInt toSigned(APInt AbsVal, bool Negative) {
130 if (AbsVal.isSignBitSet())
131 AbsVal = AbsVal.zext(nextAPIntBitWidth(AbsVal.getBitWidth()));
132 APInt Result = AbsVal;
133 if (Negative)
134 Result.negate();
135 return Result;
136}
137
139 const SourceMgr &SM) const {
140 bool ValueIsSigned = Value == Kind::Signed;
141 bool Negative = StrVal.consume_front("-");
142 bool Hex = Value == Kind::HexUpper || Value == Kind::HexLower;
143 bool MissingFormPrefix =
144 !ValueIsSigned && AlternateForm && !StrVal.consume_front("0x");
145 (void)MissingFormPrefix;
146 assert(!MissingFormPrefix && "missing alternate form prefix");
147 APInt ResultValue;
148 [[maybe_unused]] bool ParseFailure =
149 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
150 // Both the FileCheck utility and library only call this method with a valid
151 // value in StrVal. This is guaranteed by the regex returned by
152 // getWildcardRegex() above.
153 assert(!ParseFailure && "unable to represent numeric value");
154 return toSigned(ResultValue, Negative);
155}
156
158 const APInt &RightOperand, bool &Overflow) {
159 return LeftOperand.sadd_ov(RightOperand, Overflow);
160}
161
163 const APInt &RightOperand, bool &Overflow) {
164 return LeftOperand.ssub_ov(RightOperand, Overflow);
165}
166
168 const APInt &RightOperand, bool &Overflow) {
169 return LeftOperand.smul_ov(RightOperand, Overflow);
170}
171
173 const APInt &RightOperand, bool &Overflow) {
174 // Check for division by zero.
175 if (RightOperand.isZero())
177
178 return LeftOperand.sdiv_ov(RightOperand, Overflow);
179}
180
182 const APInt &RightOperand, bool &Overflow) {
183 Overflow = false;
184 return LeftOperand.slt(RightOperand) ? RightOperand : LeftOperand;
185}
186
188 const APInt &RightOperand, bool &Overflow) {
189 Overflow = false;
190 if (cantFail(exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
191 return RightOperand;
192
193 return LeftOperand;
194}
195
197 std::optional<APInt> Value = Variable->getValue();
198 if (Value)
199 return *Value;
200
202}
203
205 Expected<APInt> MaybeLeftOp = LeftOperand->eval();
206 Expected<APInt> MaybeRightOp = RightOperand->eval();
207
208 // Bubble up any error (e.g. undefined variables) in the recursive
209 // evaluation.
210 if (!MaybeLeftOp || !MaybeRightOp) {
211 Error Err = Error::success();
212 if (!MaybeLeftOp)
213 Err = joinErrors(std::move(Err), MaybeLeftOp.takeError());
214 if (!MaybeRightOp)
215 Err = joinErrors(std::move(Err), MaybeRightOp.takeError());
216 return std::move(Err);
217 }
218
219 APInt LeftOp = *MaybeLeftOp;
220 APInt RightOp = *MaybeRightOp;
221 bool Overflow;
222 // Ensure both operands have the same bitwidth.
223 unsigned LeftBitWidth = LeftOp.getBitWidth();
224 unsigned RightBitWidth = RightOp.getBitWidth();
225 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
226 LeftOp = LeftOp.sext(NewBitWidth);
227 RightOp = RightOp.sext(NewBitWidth);
228 do {
229 Expected<APInt> MaybeResult = EvalBinop(LeftOp, RightOp, Overflow);
230 if (!MaybeResult)
231 return MaybeResult.takeError();
232
233 if (!Overflow)
234 return MaybeResult;
235
236 NewBitWidth = nextAPIntBitWidth(NewBitWidth);
237 LeftOp = LeftOp.sext(NewBitWidth);
238 RightOp = RightOp.sext(NewBitWidth);
239 } while (true);
240}
241
244 Expected<ExpressionFormat> LeftFormat = LeftOperand->getImplicitFormat(SM);
245 Expected<ExpressionFormat> RightFormat = RightOperand->getImplicitFormat(SM);
246 if (!LeftFormat || !RightFormat) {
247 Error Err = Error::success();
248 if (!LeftFormat)
249 Err = joinErrors(std::move(Err), LeftFormat.takeError());
250 if (!RightFormat)
251 Err = joinErrors(std::move(Err), RightFormat.takeError());
252 return std::move(Err);
253 }
254
255 if (*LeftFormat != ExpressionFormat::Kind::NoFormat &&
256 *RightFormat != ExpressionFormat::Kind::NoFormat &&
257 *LeftFormat != *RightFormat)
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,
1264 std::vector<FileCheckDiag> *Diags) const {
1265 // Print what we know about substitutions.
1266 if (!Substitutions.empty()) {
1267 for (const auto &Substitution : Substitutions) {
1268 SmallString<256> Msg;
1269 raw_svector_ostream OS(Msg);
1270
1271 Expected<std::string> MatchedValue =
1273 // Substitution failures are handled in printNoMatch().
1274 if (!MatchedValue) {
1275 consumeError(MatchedValue.takeError());
1276 continue;
1277 }
1278
1279 OS << "with \"";
1280 OS.write_escaped(Substitution->getFromString()) << "\" equal to ";
1281 OS << *MatchedValue;
1282
1283 // We report only the start of the match/search range to suggest we are
1284 // reporting the substitutions as set at the start of the match/search.
1285 // Indicating 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_back(SM, CheckTy, getLoc(), MatchTy,
1289 SMRange(Range.Start, Range.Start), OS.str());
1290 else
1291 SM.PrintMessage(Range.Start, SourceMgr::DK_Note, OS.str());
1292 }
1293 }
1294}
1295
1298 std::vector<FileCheckDiag> *Diags) const {
1299 if (VariableDefs.empty() && NumericVariableDefs.empty())
1300 return;
1301 // Build list of variable captures.
1302 struct VarCapture {
1303 StringRef Name;
1304 SMRange Range;
1305 };
1306 SmallVector<VarCapture, 2> VarCaptures;
1307 for (const auto &VariableDef : VariableDefs) {
1308 VarCapture VC;
1309 VC.Name = VariableDef.first;
1310 StringRef Value = Context->GlobalVariableTable[VC.Name];
1311 SMLoc Start = SMLoc::getFromPointer(Value.data());
1312 SMLoc End = SMLoc::getFromPointer(Value.data() + Value.size());
1313 VC.Range = SMRange(Start, End);
1314 VarCaptures.push_back(VC);
1315 }
1316 for (const auto &VariableDef : NumericVariableDefs) {
1317 VarCapture VC;
1318 VC.Name = VariableDef.getKey();
1319 std::optional<StringRef> StrValue =
1320 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1321 if (!StrValue)
1322 continue;
1323 SMLoc Start = SMLoc::getFromPointer(StrValue->data());
1324 SMLoc End = SMLoc::getFromPointer(StrValue->data() + StrValue->size());
1325 VC.Range = SMRange(Start, End);
1326 VarCaptures.push_back(VC);
1327 }
1328 // Sort variable captures by the order in which they matched the input.
1329 // Ranges shouldn't be overlapping, so we can just compare the start.
1330 llvm::sort(VarCaptures, [](const VarCapture &A, const VarCapture &B) {
1331 if (&A == &B)
1332 return false;
1333 assert(A.Range.Start != B.Range.Start &&
1334 "unexpected overlapping variable captures");
1335 return A.Range.Start.getPointer() < B.Range.Start.getPointer();
1336 });
1337 // Create notes for the sorted captures.
1338 for (const VarCapture &VC : VarCaptures) {
1339 SmallString<256> Msg;
1340 raw_svector_ostream OS(Msg);
1341 OS << "captured var \"" << VC.Name << "\"";
1342 if (Diags)
1343 Diags->emplace_back(SM, CheckTy, getLoc(), MatchTy, VC.Range, OS.str());
1344 else
1345 SM.PrintMessage(VC.Range.Start, SourceMgr::DK_Note, OS.str(), VC.Range);
1346 }
1347}
1348
1350 const SourceMgr &SM, SMLoc Loc,
1351 Check::FileCheckType CheckTy,
1352 StringRef Buffer, size_t Pos, size_t Len,
1353 std::vector<FileCheckDiag> *Diags,
1354 bool AdjustPrevDiags = false) {
1355 SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
1356 SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
1357 SMRange Range(Start, End);
1358 if (Diags) {
1359 if (AdjustPrevDiags) {
1360 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1361 for (auto I = Diags->rbegin(), E = Diags->rend();
1362 I != E && I->CheckLoc == CheckLoc; ++I)
1363 I->MatchTy = MatchTy;
1364 } else
1365 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
1366 }
1367 return Range;
1368}
1369
1371 std::vector<FileCheckDiag> *Diags) const {
1372 // Attempt to find the closest/best fuzzy match. Usually an error happens
1373 // because some string in the output didn't exactly match. In these cases, we
1374 // would like to show the user a best guess at what "should have" matched, to
1375 // save them having to actually check the input manually.
1376 size_t NumLinesForward = 0;
1377 size_t Best = StringRef::npos;
1378 double BestQuality = 0;
1379
1380 // Arbitrarily limit quadratic search behavior stemming from long CHECK lines.
1381 if (size_t(4096) * size_t(2048) <
1382 std::min(size_t(4096), Buffer.size()) *
1383 std::max(FixedStr.size(), RegExStr.size()))
1384 return;
1385
1386 // Use an arbitrary 4k limit on how far we will search.
1387 for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
1388 if (Buffer[i] == '\n')
1389 ++NumLinesForward;
1390
1391 // Patterns have leading whitespace stripped, so skip whitespace when
1392 // looking for something which looks like a pattern.
1393 if (Buffer[i] == ' ' || Buffer[i] == '\t')
1394 continue;
1395
1396 // Compute the "quality" of this match as an arbitrary combination of the
1397 // match distance and the number of lines skipped to get to this match.
1398 unsigned Distance = computeMatchDistance(Buffer.substr(i));
1399 double Quality = Distance + (NumLinesForward / 100.);
1400
1401 if (Quality < BestQuality || Best == StringRef::npos) {
1402 Best = i;
1403 BestQuality = Quality;
1404 }
1405 }
1406
1407 // Print the "possible intended match here" line if we found something
1408 // reasonable and not equal to what we showed in the "scanning from here"
1409 // line.
1410 if (Best && Best != StringRef::npos && BestQuality < 50) {
1411 SMRange MatchRange =
1413 getCheckTy(), Buffer, Best, 0, Diags);
1414 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,
1415 "possible intended match here");
1416
1417 // FIXME: If we wanted to be really friendly we would show why the match
1418 // failed, as it can be hard to spot simple one character differences.
1419 }
1420}
1421
1424 auto VarIter = GlobalVariableTable.find(VarName);
1425 if (VarIter == GlobalVariableTable.end())
1426 return make_error<UndefVarError>(VarName);
1427
1428 return VarIter->second;
1429}
1430
1431template <class... Types>
1432NumericVariable *FileCheckPatternContext::makeNumericVariable(Types... args) {
1433 NumericVariables.push_back(std::make_unique<NumericVariable>(args...));
1434 return NumericVariables.back().get();
1435}
1436
1438FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
1439 size_t InsertIdx) {
1440 Substitutions.push_back(
1441 std::make_unique<StringSubstitution>(this, VarName, InsertIdx));
1442 return Substitutions.back().get();
1443}
1444
1445Substitution *FileCheckPatternContext::makeNumericSubstitution(
1446 StringRef ExpressionStr, std::unique_ptr<Expression> Expression,
1447 size_t InsertIdx) {
1448 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1449 this, ExpressionStr, std::move(Expression), InsertIdx));
1450 return Substitutions.back().get();
1451}
1452
1453size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
1454 // Offset keeps track of the current offset within the input Str
1455 size_t Offset = 0;
1456 // [...] Nesting depth
1457 size_t BracketDepth = 0;
1458
1459 while (!Str.empty()) {
1460 if (Str.starts_with("]]") && BracketDepth == 0)
1461 return Offset;
1462 if (Str[0] == '\\') {
1463 // Backslash escapes the next char within regexes, so skip them both.
1464 Str = Str.substr(2);
1465 Offset += 2;
1466 } else {
1467 switch (Str[0]) {
1468 default:
1469 break;
1470 case '[':
1471 BracketDepth++;
1472 break;
1473 case ']':
1474 if (BracketDepth == 0) {
1475 SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
1477 "missing closing \"]\" for regex variable");
1478 exit(1);
1479 }
1480 BracketDepth--;
1481 break;
1482 }
1483 Str = Str.substr(1);
1484 Offset++;
1485 }
1486 }
1487
1488 return StringRef::npos;
1489}
1490
1493 OutputBuffer.reserve(MB.getBufferSize());
1494
1495 for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
1496 Ptr != End; ++Ptr) {
1497 // Eliminate trailing dosish \r.
1498 if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
1499 continue;
1500 }
1501
1502 // If current char is not a horizontal whitespace or if horizontal
1503 // whitespace canonicalization is disabled, dump it to output as is.
1504 if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
1505 OutputBuffer.push_back(*Ptr);
1506 continue;
1507 }
1508
1509 // Otherwise, add one space and advance over neighboring space.
1510 OutputBuffer.push_back(' ');
1511 while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
1512 ++Ptr;
1513 }
1514
1515 // Add a null byte and then return all but that byte.
1516 OutputBuffer.push_back('\0');
1517 return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
1518}
1519
1523 SMRange InputRange, StringRef Note)
1525 auto Start = SM.getLineAndColumn(InputRange.Start);
1526 auto End = SM.getLineAndColumn(InputRange.End);
1527 InputStartLine = Start.first;
1528 InputStartCol = Start.second;
1529 InputEndLine = End.first;
1530 InputEndCol = End.second;
1531}
1532
1533static bool IsPartOfWord(char c) {
1534 return (isAlnum(c) || c == '-' || c == '_');
1535}
1536
1538 assert(Count > 0 && "zero and negative counts are not supported");
1539 assert((C == 1 || Kind == CheckPlain) &&
1540 "count supported only for plain CHECK directives");
1541 Count = C;
1542 return *this;
1543}
1544
1546 if (Modifiers.none())
1547 return "";
1548 std::string Ret;
1549 raw_string_ostream OS(Ret);
1550 OS << '{';
1551 if (isLiteralMatch())
1552 OS << "LITERAL";
1553 OS << '}';
1554 return Ret;
1555}
1556
1558 // Append directive modifiers.
1559 auto WithModifiers = [this, Prefix](StringRef Str) -> std::string {
1560 return (Prefix + Str + getModifiersDescription()).str();
1561 };
1562
1563 switch (Kind) {
1564 case Check::CheckNone:
1565 return "invalid";
1567 return "misspelled";
1568 case Check::CheckPlain:
1569 if (Count > 1)
1570 return WithModifiers("-COUNT");
1571 return WithModifiers("");
1572 case Check::CheckNext:
1573 return WithModifiers("-NEXT");
1574 case Check::CheckSame:
1575 return WithModifiers("-SAME");
1576 case Check::CheckNot:
1577 return WithModifiers("-NOT");
1578 case Check::CheckDAG:
1579 return WithModifiers("-DAG");
1580 case Check::CheckLabel:
1581 return WithModifiers("-LABEL");
1582 case Check::CheckEmpty:
1583 return WithModifiers("-EMPTY");
1585 return std::string(Prefix);
1586 case Check::CheckEOF:
1587 return "implicit EOF";
1588 case Check::CheckBadNot:
1589 return "bad NOT";
1591 return "bad COUNT";
1592 }
1593 llvm_unreachable("unknown FileCheckType");
1594}
1595
1596static std::pair<Check::FileCheckType, StringRef>
1598 bool &Misspelled) {
1599 if (Buffer.size() <= Prefix.size())
1600 return {Check::CheckNone, StringRef()};
1601
1602 StringRef Rest = Buffer.drop_front(Prefix.size());
1603 // Check for comment.
1604 if (llvm::is_contained(Req.CommentPrefixes, Prefix)) {
1605 if (Rest.consume_front(":"))
1606 return {Check::CheckComment, Rest};
1607 // Ignore a comment prefix if it has a suffix like "-NOT".
1608 return {Check::CheckNone, StringRef()};
1609 }
1610
1611 auto ConsumeModifiers = [&](Check::FileCheckType Ret)
1612 -> std::pair<Check::FileCheckType, StringRef> {
1613 if (Rest.consume_front(":"))
1614 return {Ret, Rest};
1615 if (!Rest.consume_front("{"))
1616 return {Check::CheckNone, StringRef()};
1617
1618 // Parse the modifiers, speparated by commas.
1619 do {
1620 // Allow whitespace in modifiers list.
1621 Rest = Rest.ltrim();
1622 if (Rest.consume_front("LITERAL"))
1623 Ret.setLiteralMatch();
1624 else
1625 return {Check::CheckNone, Rest};
1626 // Allow whitespace in modifiers list.
1627 Rest = Rest.ltrim();
1628 } while (Rest.consume_front(","));
1629 if (!Rest.consume_front("}:"))
1630 return {Check::CheckNone, Rest};
1631 return {Ret, Rest};
1632 };
1633
1634 // Verify that the prefix is followed by directive modifiers or a colon.
1635 if (Rest.consume_front(":"))
1636 return {Check::CheckPlain, Rest};
1637 if (Rest.front() == '{')
1638 return ConsumeModifiers(Check::CheckPlain);
1639
1640 if (Rest.consume_front("_"))
1641 Misspelled = true;
1642 else if (!Rest.consume_front("-"))
1643 return {Check::CheckNone, StringRef()};
1644
1645 if (Rest.consume_front("COUNT-")) {
1646 int64_t Count;
1647 if (Rest.consumeInteger(10, Count))
1648 // Error happened in parsing integer.
1649 return {Check::CheckBadCount, Rest};
1650 if (Count <= 0 || Count > INT32_MAX)
1651 return {Check::CheckBadCount, Rest};
1652 if (Rest.front() != ':' && Rest.front() != '{')
1653 return {Check::CheckBadCount, Rest};
1654 return ConsumeModifiers(
1656 }
1657
1658 // You can't combine -NOT with another suffix.
1659 if (Rest.starts_with("DAG-NOT:") || Rest.starts_with("NOT-DAG:") ||
1660 Rest.starts_with("NEXT-NOT:") || Rest.starts_with("NOT-NEXT:") ||
1661 Rest.starts_with("SAME-NOT:") || Rest.starts_with("NOT-SAME:") ||
1662 Rest.starts_with("EMPTY-NOT:") || Rest.starts_with("NOT-EMPTY:"))
1663 return {Check::CheckBadNot, Rest};
1664
1665 if (Rest.consume_front("NEXT"))
1666 return ConsumeModifiers(Check::CheckNext);
1667
1668 if (Rest.consume_front("SAME"))
1669 return ConsumeModifiers(Check::CheckSame);
1670
1671 if (Rest.consume_front("NOT"))
1672 return ConsumeModifiers(Check::CheckNot);
1673
1674 if (Rest.consume_front("DAG"))
1675 return ConsumeModifiers(Check::CheckDAG);
1676
1677 if (Rest.consume_front("LABEL"))
1678 return ConsumeModifiers(Check::CheckLabel);
1679
1680 if (Rest.consume_front("EMPTY"))
1681 return ConsumeModifiers(Check::CheckEmpty);
1682
1683 return {Check::CheckNone, Rest};
1684}
1685
1686static std::pair<Check::FileCheckType, StringRef>
1688 bool Misspelled = false;
1689 auto Res = FindCheckType(Req, Buffer, Prefix, Misspelled);
1690 if (Res.first != Check::CheckNone && Misspelled)
1691 return {Check::CheckMisspelled, Res.second};
1692 return Res;
1693}
1694
1695// From the given position, find the next character after the word.
1696static size_t SkipWord(StringRef Str, size_t Loc) {
1697 while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
1698 ++Loc;
1699 return Loc;
1700}
1701
1702static const char *DefaultCheckPrefixes[] = {"CHECK"};
1703static const char *DefaultCommentPrefixes[] = {"COM", "RUN"};
1704
1706 if (Req.CheckPrefixes.empty()) {
1708 Req.IsDefaultCheckPrefix = true;
1709 }
1710 if (Req.CommentPrefixes.empty())
1712}
1713
1715 /// Prefixes and their first occurrence past the current position.
1718
1720 ArrayRef<StringRef> CommentPrefixes, StringRef Input)
1721 : Input(Input) {
1722 for (StringRef Prefix : CheckPrefixes)
1723 Prefixes.push_back({Prefix, Input.find(Prefix)});
1724 for (StringRef Prefix : CommentPrefixes)
1725 Prefixes.push_back({Prefix, Input.find(Prefix)});
1726
1727 // Sort by descending length.
1729 [](auto A, auto B) { return A.first.size() > B.first.size(); });
1730 }
1731
1732 /// Find the next match of a prefix in Buffer.
1733 /// Returns empty StringRef if not found.
1735 assert(Buffer.data() >= Input.data() &&
1736 Buffer.data() + Buffer.size() == Input.data() + Input.size() &&
1737 "Buffer must be suffix of Input");
1738
1739 size_t From = Buffer.data() - Input.data();
1740 StringRef Match;
1741 for (auto &[Prefix, Pos] : Prefixes) {
1742 // If the last occurrence was before From, find the next one after From.
1743 if (Pos < From)
1744 Pos = Input.find(Prefix, From);
1745 // Find the first prefix with the lowest position.
1746 if (Pos != StringRef::npos &&
1747 (Match.empty() || size_t(Match.data() - Input.data()) > Pos))
1748 Match = StringRef(Input.substr(Pos, Prefix.size()));
1749 }
1750 return Match;
1751 }
1752};
1753
1754/// Searches the buffer for the first prefix in the prefix regular expression.
1755///
1756/// This searches the buffer using the provided regular expression, however it
1757/// enforces constraints beyond that:
1758/// 1) The found prefix must not be a suffix of something that looks like
1759/// a valid prefix.
1760/// 2) The found prefix must be followed by a valid check type suffix using \c
1761/// FindCheckType above.
1762///
1763/// \returns a pair of StringRefs into the Buffer, which combines:
1764/// - the first match of the regular expression to satisfy these two is
1765/// returned,
1766/// otherwise an empty StringRef is returned to indicate failure.
1767/// - buffer rewound to the location right after parsed suffix, for parsing
1768/// to continue from
1769///
1770/// If this routine returns a valid prefix, it will also shrink \p Buffer to
1771/// start at the beginning of the returned prefix, increment \p LineNumber for
1772/// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1773/// check found by examining the suffix.
1774///
1775/// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1776/// is unspecified.
1777static std::pair<StringRef, StringRef>
1779 StringRef &Buffer, unsigned &LineNumber,
1780 Check::FileCheckType &CheckTy) {
1781 while (!Buffer.empty()) {
1782 // Find the first (longest) prefix match.
1783 StringRef Prefix = Matcher.match(Buffer);
1784 if (Prefix.empty())
1785 // No match at all, bail.
1786 return {StringRef(), StringRef()};
1787
1788 assert(Prefix.data() >= Buffer.data() &&
1789 Prefix.data() < Buffer.data() + Buffer.size() &&
1790 "Prefix doesn't start inside of buffer!");
1791 size_t Loc = Prefix.data() - Buffer.data();
1792 StringRef Skipped = Buffer.substr(0, Loc);
1793 Buffer = Buffer.drop_front(Loc);
1794 LineNumber += Skipped.count('\n');
1795
1796 // Check that the matched prefix isn't a suffix of some other check-like
1797 // word.
1798 // FIXME: This is a very ad-hoc check. it would be better handled in some
1799 // other way. Among other things it seems hard to distinguish between
1800 // intentional and unintentional uses of this feature.
1801 if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
1802 // Now extract the type.
1803 StringRef AfterSuffix;
1804 std::tie(CheckTy, AfterSuffix) = FindCheckType(Req, Buffer, Prefix);
1805
1806 // If we've found a valid check type for this prefix, we're done.
1807 if (CheckTy != Check::CheckNone)
1808 return {Prefix, AfterSuffix};
1809 }
1810
1811 // If we didn't successfully find a prefix, we need to skip this invalid
1812 // prefix and continue scanning. We directly skip the prefix that was
1813 // matched and any additional parts of that check-like word.
1814 Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
1815 }
1816
1817 // We ran out of buffer while skipping partial matches so give up.
1818 return {StringRef(), StringRef()};
1819}
1820
1822 assert(!LineVariable && "@LINE pseudo numeric variable already created");
1823 StringRef LineName = "@LINE";
1824 LineVariable = makeNumericVariable(
1826 GlobalNumericVariableTable[LineName] = LineVariable;
1827}
1828
1830 : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()) {}
1831
1832FileCheck::~FileCheck() = default;
1833
1835 SourceMgr &SM, StringRef Buffer,
1836 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1837 if (ImpPatBufferIDRange)
1838 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1839
1840 Error DefineError =
1841 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1842 if (DefineError) {
1843 logAllUnhandledErrors(std::move(DefineError), errs());
1844 return true;
1845 }
1846
1847 PatternContext->createLineVariable();
1848
1849 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1850 for (StringRef PatternString : Req.ImplicitCheckNot) {
1851 // Create a buffer with fake command line content in order to display the
1852 // command line option responsible for the specific implicit CHECK-NOT.
1853 std::string Prefix = "-implicit-check-not='";
1854 std::string Suffix = "'";
1855 std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
1856 (Prefix + PatternString + Suffix).str(), "command line");
1857
1858 StringRef PatternInBuffer =
1859 CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
1860 unsigned BufferID = SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
1861 if (ImpPatBufferIDRange) {
1862 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1863 ImpPatBufferIDRange->first = BufferID;
1864 ImpPatBufferIDRange->second = BufferID + 1;
1865 } else {
1866 assert(BufferID == ImpPatBufferIDRange->second &&
1867 "expected consecutive source buffer IDs");
1868 ++ImpPatBufferIDRange->second;
1869 }
1870 }
1871
1872 ImplicitNegativeChecks.emplace_back(
1873 Pattern(Check::CheckNot, PatternContext.get()),
1874 StringRef("IMPLICIT-CHECK"));
1875 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1876 PatternInBuffer, "IMPLICIT-CHECK", SM, Req);
1877 }
1878
1879 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1880 ImplicitNegativeChecks;
1881 // LineNumber keeps track of the line on which CheckPrefix instances are
1882 // found.
1883 unsigned LineNumber = 1;
1884
1885 addDefaultPrefixes(Req);
1886 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1887 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1888 Req.CheckPrefixes.end());
1889 const size_t DistinctPrefixes = PrefixesNotFound.size();
1890 while (true) {
1891 Check::FileCheckType CheckTy;
1892
1893 // See if a prefix occurs in the memory buffer.
1894 StringRef UsedPrefix;
1895 StringRef AfterSuffix;
1896 std::tie(UsedPrefix, AfterSuffix) =
1897 FindFirstMatchingPrefix(Req, Matcher, Buffer, LineNumber, CheckTy);
1898 if (UsedPrefix.empty())
1899 break;
1900 if (CheckTy != Check::CheckComment)
1901 PrefixesNotFound.erase(UsedPrefix);
1902
1903 assert(UsedPrefix.data() == Buffer.data() &&
1904 "Failed to move Buffer's start forward, or pointed prefix outside "
1905 "of the buffer!");
1906 assert(AfterSuffix.data() >= Buffer.data() &&
1907 AfterSuffix.data() < Buffer.data() + Buffer.size() &&
1908 "Parsing after suffix doesn't start inside of buffer!");
1909
1910 // Location to use for error messages.
1911 const char *UsedPrefixStart = UsedPrefix.data();
1912
1913 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1914 // suffix was processed).
1915 Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size())
1916 : AfterSuffix;
1917
1918 // Complain about misspelled directives.
1919 if (CheckTy == Check::CheckMisspelled) {
1920 StringRef UsedDirective(UsedPrefix.data(),
1921 AfterSuffix.data() - UsedPrefix.data());
1922 SM.PrintMessage(SMLoc::getFromPointer(UsedDirective.data()),
1924 "misspelled directive '" + UsedDirective + "'");
1925 return true;
1926 }
1927
1928 // Complain about useful-looking but unsupported suffixes.
1929 if (CheckTy == Check::CheckBadNot) {
1931 "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
1932 return true;
1933 }
1934
1935 // Complain about invalid count specification.
1936 if (CheckTy == Check::CheckBadCount) {
1938 "invalid count in -COUNT specification on prefix '" +
1939 UsedPrefix + "'");
1940 return true;
1941 }
1942
1943 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1944 // leading whitespace.
1945 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1946 Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
1947
1948 // Scan ahead to the end of line.
1949 size_t EOL = Buffer.find_first_of("\n\r");
1950
1951 // Remember the location of the start of the pattern, for diagnostics.
1952 SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
1953
1954 // Extract the pattern from the buffer.
1955 StringRef PatternBuffer = Buffer.substr(0, EOL);
1956 Buffer = Buffer.substr(EOL);
1957
1958 // If this is a comment, we're done.
1959 if (CheckTy == Check::CheckComment)
1960 continue;
1961
1962 // Parse the pattern.
1963 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1964 if (P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1965 return true;
1966
1967 // Verify that CHECK-LABEL lines do not define or use variables
1968 if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
1969 SM.PrintMessage(
1971 "found '" + UsedPrefix + "-LABEL:'"
1972 " with variable definition or use");
1973 return true;
1974 }
1975
1976 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1977 if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
1978 CheckTy == Check::CheckEmpty) &&
1979 CheckStrings.empty()) {
1980 StringRef Type = CheckTy == Check::CheckNext
1981 ? "NEXT"
1982 : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
1983 SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
1985 "found '" + UsedPrefix + "-" + Type +
1986 "' without previous '" + UsedPrefix + ": line");
1987 return true;
1988 }
1989
1990 // Handle CHECK-DAG/-NOT.
1991 if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
1992 DagNotMatches.emplace_back(P, UsedPrefix);
1993 continue;
1994 }
1995
1996 // Okay, add the string we captured to the output vector and move on.
1997 CheckStrings.emplace_back(std::move(P), UsedPrefix, PatternLoc,
1998 std::move(DagNotMatches));
1999 DagNotMatches = ImplicitNegativeChecks;
2000 }
2001
2002 // When there are no used prefixes we report an error except in the case that
2003 // no prefix is specified explicitly but -implicit-check-not is specified.
2004 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
2005 const bool SomePrefixesUnexpectedlyNotUsed =
2006 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
2007 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
2008 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
2009 errs() << "error: no check strings found with prefix"
2010 << (PrefixesNotFound.size() > 1 ? "es " : " ");
2011 ListSeparator LS;
2012 for (StringRef MissingPrefix : PrefixesNotFound)
2013 errs() << LS << "\'" << MissingPrefix << ":'";
2014 errs() << '\n';
2015 return true;
2016 }
2017
2018 // Add an EOF pattern for any trailing --implicit-check-not/CHECK-DAG/-NOTs,
2019 // and use the first prefix as a filler for the error message.
2020 if (!DagNotMatches.empty()) {
2021 CheckStrings.emplace_back(
2022 Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
2023 *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()),
2024 std::move(DagNotMatches));
2025 }
2026
2027 return false;
2028}
2029
2030/// Returns either (1) \c ErrorSuccess if there was no error or (2)
2031/// \c ErrorReported if an error was reported, such as an unexpected match.
2032static Error printMatch(bool ExpectedMatch, const SourceMgr &SM,
2033 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2034 int MatchedCount, StringRef Buffer,
2035 Pattern::MatchResult MatchResult,
2036 const FileCheckRequest &Req,
2037 std::vector<FileCheckDiag> *Diags) {
2038 // Suppress some verbosity if there's no error.
2039 bool HasError = !ExpectedMatch || MatchResult.TheError;
2040 bool PrintDiag = true;
2041 if (!HasError) {
2042 if (!Req.Verbose)
2043 return ErrorReported::reportedOrSuccess(HasError);
2044 if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
2045 return ErrorReported::reportedOrSuccess(HasError);
2046 // Due to their verbosity, we don't print verbose diagnostics here if we're
2047 // gathering them for Diags to be rendered elsewhere, but we always print
2048 // other diagnostics.
2049 PrintDiag = !Diags;
2050 }
2051
2052 // Add "found" diagnostic, substitutions, and variable definitions to Diags.
2053 FileCheckDiag::MatchType MatchTy = ExpectedMatch
2056 SMRange MatchRange = ProcessMatchResult(MatchTy, SM, Loc, Pat.getCheckTy(),
2057 Buffer, MatchResult.TheMatch->Pos,
2058 MatchResult.TheMatch->Len, Diags);
2059 if (Diags) {
2060 Pat.printSubstitutions(SM, Buffer, MatchRange, MatchTy, Diags);
2061 Pat.printVariableDefs(SM, MatchTy, Diags);
2062 }
2063 if (!PrintDiag) {
2064 assert(!HasError && "expected to report more diagnostics for error");
2065 return ErrorReported::reportedOrSuccess(HasError);
2066 }
2067
2068 // Print the match.
2069 std::string Message = formatv("{0}: {1} string found in input",
2070 Pat.getCheckTy().getDescription(Prefix),
2071 (ExpectedMatch ? "expected" : "excluded"))
2072 .str();
2073 if (Pat.getCount() > 1)
2074 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2075 SM.PrintMessage(
2076 Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
2077 SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
2078 {MatchRange});
2079
2080 // Print additional information, which can be useful even if there are errors.
2081 Pat.printSubstitutions(SM, Buffer, MatchRange, MatchTy, nullptr);
2082 Pat.printVariableDefs(SM, MatchTy, nullptr);
2083
2084 // Print errors and add them to Diags. We report these errors after the match
2085 // itself because we found them after the match. If we had found them before
2086 // the match, we'd be in printNoMatch.
2087 handleAllErrors(std::move(MatchResult.TheError),
2088 [&](const ErrorDiagnostic &E) {
2089 E.log(errs());
2090 if (Diags) {
2091 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2092 FileCheckDiag::MatchFoundErrorNote,
2093 E.getRange(), E.getMessage().str());
2094 }
2095 });
2096 return ErrorReported::reportedOrSuccess(HasError);
2097}
2098
2099/// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2100/// \c ErrorReported if an error was reported, such as an expected match not
2101/// found.
2102static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM,
2103 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2104 int MatchedCount, StringRef Buffer, Error MatchError,
2105 bool VerboseVerbose,
2106 std::vector<FileCheckDiag> *Diags) {
2107 // Print any pattern errors, and record them to be added to Diags later.
2108 bool HasError = ExpectedMatch;
2109 bool HasPatternError = false;
2110 FileCheckDiag::MatchType MatchTy = ExpectedMatch
2115 std::move(MatchError),
2116 [&](const ErrorDiagnostic &E) {
2117 HasError = HasPatternError = true;
2119 E.log(errs());
2120 if (Diags)
2121 ErrorMsgs.push_back(E.getMessage().str());
2122 },
2123 // NotFoundError is why printNoMatch was invoked.
2124 [](const NotFoundError &E) {});
2125
2126 // Suppress some verbosity if there's no error.
2127 bool PrintDiag = true;
2128 if (!HasError) {
2129 if (!VerboseVerbose)
2130 return ErrorReported::reportedOrSuccess(HasError);
2131 // Due to their verbosity, we don't print verbose diagnostics here if we're
2132 // gathering them for Diags to be rendered elsewhere, but we always print
2133 // other diagnostics.
2134 PrintDiag = !Diags;
2135 }
2136
2137 // Add "not found" diagnostic, substitutions, and pattern errors to Diags.
2138 //
2139 // We handle Diags a little differently than the errors we print directly:
2140 // we add the "not found" diagnostic to Diags even if there are pattern
2141 // errors. The reason is that we need to attach pattern errors as notes
2142 // somewhere in the input, and the input search range from the "not found"
2143 // diagnostic is all we have to anchor them.
2144 SMRange SearchRange = ProcessMatchResult(MatchTy, SM, Loc, Pat.getCheckTy(),
2145 Buffer, 0, Buffer.size(), Diags);
2146 if (Diags) {
2147 SMRange NoteRange = SMRange(SearchRange.Start, SearchRange.Start);
2148 for (StringRef ErrorMsg : ErrorMsgs)
2149 Diags->emplace_back(SM, Pat.getCheckTy(), Loc, MatchTy, NoteRange,
2150 ErrorMsg);
2151 Pat.printSubstitutions(SM, Buffer, SearchRange, MatchTy, Diags);
2152 }
2153 if (!PrintDiag) {
2154 assert(!HasError && "expected to report more diagnostics for error");
2155 return ErrorReported::reportedOrSuccess(HasError);
2156 }
2157
2158 // Print "not found" diagnostic, except that's implied if we already printed a
2159 // pattern error.
2160 if (!HasPatternError) {
2161 std::string Message = formatv("{0}: {1} string not found in input",
2162 Pat.getCheckTy().getDescription(Prefix),
2163 (ExpectedMatch ? "expected" : "excluded"))
2164 .str();
2165 if (Pat.getCount() > 1)
2166 Message +=
2167 formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2168 SM.PrintMessage(Loc,
2169 ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark,
2170 Message);
2171 SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note,
2172 "scanning from here");
2173 }
2174
2175 // Print additional information, which can be useful even after a pattern
2176 // error.
2177 Pat.printSubstitutions(SM, Buffer, SearchRange, MatchTy, nullptr);
2178 if (ExpectedMatch)
2179 Pat.printFuzzyMatch(SM, Buffer, Diags);
2180 return ErrorReported::reportedOrSuccess(HasError);
2181}
2182
2183/// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2184/// \c ErrorReported if an error was reported.
2185static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM,
2186 StringRef Prefix, SMLoc Loc, const Pattern &Pat,
2187 int MatchedCount, StringRef Buffer,
2188 Pattern::MatchResult MatchResult,
2189 const FileCheckRequest &Req,
2190 std::vector<FileCheckDiag> *Diags) {
2191 if (MatchResult.TheMatch)
2192 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2193 std::move(MatchResult), Req, Diags);
2194 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2195 std::move(MatchResult.TheError), Req.VerboseVerbose,
2196 Diags);
2197}
2198
2199/// Counts the number of newlines in the specified range.
2201 const char *&FirstNewLine) {
2202 unsigned NumNewLines = 0;
2203 while (true) {
2204 // Scan for newline.
2205 Range = Range.substr(Range.find_first_of("\n\r"));
2206 if (Range.empty())
2207 return NumNewLines;
2208
2209 ++NumNewLines;
2210
2211 // Handle \n\r and \r\n as a single newline.
2212 if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
2213 (Range[0] != Range[1]))
2214 Range = Range.substr(1);
2215 Range = Range.substr(1);
2216
2217 if (NumNewLines == 1)
2218 FirstNewLine = Range.begin();
2219 }
2220}
2221
2223 bool IsLabelScanMode, size_t &MatchLen,
2224 FileCheckRequest &Req,
2225 std::vector<FileCheckDiag> *Diags) const {
2226 size_t LastPos = 0;
2227 std::vector<const DagNotPrefixInfo *> NotStrings;
2228
2229 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
2230 // bounds; we have not processed variable definitions within the bounded block
2231 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
2232 // over the block again (including the last CHECK-LABEL) in normal mode.
2233 if (!IsLabelScanMode) {
2234 // Match "dag strings" (with mixed "not strings" if any).
2235 LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
2236 if (LastPos == StringRef::npos)
2237 return StringRef::npos;
2238 }
2239
2240 // Match itself from the last position after matching CHECK-DAG.
2241 size_t LastMatchEnd = LastPos;
2242 size_t FirstMatchPos = 0;
2243 // Go match the pattern Count times. Majority of patterns only match with
2244 // count 1 though.
2245 assert(Pat.getCount() != 0 && "pattern count can not be zero");
2246 for (int i = 1; i <= Pat.getCount(); i++) {
2247 StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
2248 // get a match at current start point
2249 Pattern::MatchResult MatchResult = Pat.match(MatchBuffer, SM);
2250
2251 // report
2252 if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, Prefix, Loc,
2253 Pat, i, MatchBuffer,
2254 std::move(MatchResult), Req, Diags)) {
2255 cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2256 return StringRef::npos;
2257 }
2258
2259 size_t MatchPos = MatchResult.TheMatch->Pos;
2260 if (i == 1)
2261 FirstMatchPos = LastPos + MatchPos;
2262
2263 // move start point after the match
2264 LastMatchEnd += MatchPos + MatchResult.TheMatch->Len;
2265 }
2266 // Full match len counts from first match pos.
2267 MatchLen = LastMatchEnd - FirstMatchPos;
2268
2269 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
2270 // or CHECK-NOT
2271 if (!IsLabelScanMode) {
2272 size_t MatchPos = FirstMatchPos - LastPos;
2273 StringRef MatchBuffer = Buffer.substr(LastPos);
2274 StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
2275
2276 // If this check is a "CHECK-NEXT", verify that the previous match was on
2277 // the previous line (i.e. that there is one newline between them).
2278 if (CheckNext(SM, SkippedRegion)) {
2280 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2281 Diags, Req.Verbose);
2282 return StringRef::npos;
2283 }
2284
2285 // If this check is a "CHECK-SAME", verify that the previous match was on
2286 // the same line (i.e. that there is no newline between them).
2287 if (CheckSame(SM, SkippedRegion)) {
2289 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2290 Diags, Req.Verbose);
2291 return StringRef::npos;
2292 }
2293
2294 // If this match had "not strings", verify that they don't exist in the
2295 // skipped region.
2296 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2297 return StringRef::npos;
2298 }
2299
2300 return FirstMatchPos;
2301}
2302
2303bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
2304 if (Pat.getCheckTy() != Check::CheckNext &&
2305 Pat.getCheckTy() != Check::CheckEmpty)
2306 return false;
2307
2308 Twine CheckName =
2309 Prefix +
2310 Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
2311
2312 // Count the number of newlines between the previous match and this one.
2313 const char *FirstNewLine = nullptr;
2314 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
2315
2316 if (NumNewLines == 0) {
2318 CheckName + ": is on the same line as previous match");
2320 "'next' match was here");
2322 "previous match ended here");
2323 return true;
2324 }
2325
2326 if (NumNewLines != 1) {
2328 CheckName +
2329 ": is not on the line after the previous match");
2331 "'next' match was here");
2333 "previous match ended here");
2335 "non-matching line after previous match is here");
2336 return true;
2337 }
2338
2339 return false;
2340}
2341
2342bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
2343 if (Pat.getCheckTy() != Check::CheckSame)
2344 return false;
2345
2346 // Count the number of newlines between the previous match and this one.
2347 const char *FirstNewLine = nullptr;
2348 unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
2349
2350 if (NumNewLines != 0) {
2352 Prefix +
2353 "-SAME: is not on the same line as the previous match");
2355 "'next' match was here");
2357 "previous match ended here");
2358 return true;
2359 }
2360
2361 return false;
2362}
2363
2365 const SourceMgr &SM, StringRef Buffer,
2366 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2367 const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const {
2368 bool DirectiveFail = false;
2369 for (auto NotInfo : NotStrings) {
2370 assert((NotInfo->DagNotPat.getCheckTy() == Check::CheckNot) &&
2371 "Expect CHECK-NOT!");
2372 Pattern::MatchResult MatchResult = NotInfo->DagNotPat.match(Buffer, SM);
2373 if (Error Err = reportMatchResult(
2374 /*ExpectedMatch=*/false, SM, NotInfo->DagNotPrefix,
2375 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2376 std::move(MatchResult), Req, Diags)) {
2377 cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2378 DirectiveFail = true;
2379 continue;
2380 }
2381 }
2382 return DirectiveFail;
2383}
2384
2385size_t
2387 std::vector<const DagNotPrefixInfo *> &NotStrings,
2388 const FileCheckRequest &Req,
2389 std::vector<FileCheckDiag> *Diags) const {
2390 if (DagNotStrings.empty())
2391 return 0;
2392
2393 // The start of the search range.
2394 size_t StartPos = 0;
2395
2396 struct MatchRange {
2397 size_t Pos;
2398 size_t End;
2399 };
2400 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
2401 // ranges are erased from this list once they are no longer in the search
2402 // range.
2403 std::list<MatchRange> MatchRanges;
2404
2405 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
2406 // group, so we don't use a range-based for loop here.
2407 for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
2408 PatItr != PatEnd; ++PatItr) {
2409 const Pattern &Pat = PatItr->DagNotPat;
2410 const StringRef DNPrefix = PatItr->DagNotPrefix;
2411 assert((Pat.getCheckTy() == Check::CheckDAG ||
2412 Pat.getCheckTy() == Check::CheckNot) &&
2413 "Invalid CHECK-DAG or CHECK-NOT!");
2414
2415 if (Pat.getCheckTy() == Check::CheckNot) {
2416 NotStrings.push_back(&*PatItr);
2417 continue;
2418 }
2419
2420 assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
2421
2422 // CHECK-DAG always matches from the start.
2423 size_t MatchLen = 0, MatchPos = StartPos;
2424
2425 // Search for a match that doesn't overlap a previous match in this
2426 // CHECK-DAG group.
2427 for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
2428 StringRef MatchBuffer = Buffer.substr(MatchPos);
2429 Pattern::MatchResult MatchResult = Pat.match(MatchBuffer, SM);
2430 // With a group of CHECK-DAGs, a single mismatching means the match on
2431 // that group of CHECK-DAGs fails immediately.
2432 if (MatchResult.TheError || Req.VerboseVerbose) {
2433 if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, DNPrefix,
2434 Pat.getLoc(), Pat, 1, MatchBuffer,
2435 std::move(MatchResult), Req, Diags)) {
2436 cantFail(
2437 handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
2438 return StringRef::npos;
2439 }
2440 }
2441 MatchLen = MatchResult.TheMatch->Len;
2442 // Re-calc it as the offset relative to the start of the original
2443 // string.
2444 MatchPos += MatchResult.TheMatch->Pos;
2445 MatchRange M{MatchPos, MatchPos + MatchLen};
2446 if (Req.AllowDeprecatedDagOverlap) {
2447 // We don't need to track all matches in this mode, so we just maintain
2448 // one match range that encompasses the current CHECK-DAG group's
2449 // matches.
2450 if (MatchRanges.empty())
2451 MatchRanges.insert(MatchRanges.end(), M);
2452 else {
2453 auto Block = MatchRanges.begin();
2454 Block->Pos = std::min(Block->Pos, M.Pos);
2455 Block->End = std::max(Block->End, M.End);
2456 }
2457 break;
2458 }
2459 // Iterate previous matches until overlapping match or insertion point.
2460 bool Overlap = false;
2461 for (; MI != ME; ++MI) {
2462 if (M.Pos < MI->End) {
2463 // !Overlap => New match has no overlap and is before this old match.
2464 // Overlap => New match overlaps this old match.
2465 Overlap = MI->Pos < M.End;
2466 break;
2467 }
2468 }
2469 if (!Overlap) {
2470 // Insert non-overlapping match into list.
2471 MatchRanges.insert(MI, M);
2472 break;
2473 }
2474 if (Req.VerboseVerbose) {
2475 // Due to their verbosity, we don't print verbose diagnostics here if
2476 // we're gathering them for a different rendering, but we always print
2477 // other diagnostics.
2478 if (!Diags) {
2479 SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
2480 SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
2481 SMRange OldRange(OldStart, OldEnd);
2482 SM.PrintMessage(OldStart, SourceMgr::DK_Note,
2483 "match discarded, overlaps earlier DAG match here",
2484 {OldRange});
2485 } else {
2486 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2487 for (auto I = Diags->rbegin(), E = Diags->rend();
2488 I != E && I->CheckLoc == CheckLoc; ++I)
2490 }
2491 }
2492 MatchPos = MI->End;
2493 }
2494 if (!Req.VerboseVerbose)
2496 /*ExpectedMatch=*/true, SM, DNPrefix, Pat.getLoc(), Pat, 1, Buffer,
2497 Pattern::MatchResult(MatchPos, MatchLen, Error::success()), Req,
2498 Diags));
2499
2500 // Handle the end of a CHECK-DAG group.
2501 if (std::next(PatItr) == PatEnd ||
2502 std::next(PatItr)->DagNotPat.getCheckTy() == Check::CheckNot) {
2503 if (!NotStrings.empty()) {
2504 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
2505 // CHECK-DAG, verify that there are no 'not' strings occurred in that
2506 // region.
2507 StringRef SkippedRegion =
2508 Buffer.slice(StartPos, MatchRanges.begin()->Pos);
2509 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2510 return StringRef::npos;
2511 // Clear "not strings".
2512 NotStrings.clear();
2513 }
2514 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
2515 // end of this CHECK-DAG group's match range.
2516 StartPos = MatchRanges.rbegin()->End;
2517 // Don't waste time checking for (impossible) overlaps before that.
2518 MatchRanges.clear();
2519 }
2520 }
2521
2522 return StartPos;
2523}
2524
2525static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes,
2526 ArrayRef<StringRef> SuppliedPrefixes) {
2527 for (StringRef Prefix : SuppliedPrefixes) {
2528 if (Prefix.empty()) {
2529 errs() << "error: supplied " << Kind << " prefix must not be the empty "
2530 << "string\n";
2531 return false;
2532 }
2533 static const Regex Validator("^[a-zA-Z0-9_-]*$");
2534 if (!Validator.match(Prefix)) {
2535 errs() << "error: supplied " << Kind << " prefix must start with a "
2536 << "letter and contain only alphanumeric characters, hyphens, and "
2537 << "underscores: '" << Prefix << "'\n";
2538 return false;
2539 }
2540 if (!UniquePrefixes.insert(Prefix).second) {
2541 errs() << "error: supplied " << Kind << " prefix must be unique among "
2542 << "check and comment prefixes: '" << Prefix << "'\n";
2543 return false;
2544 }
2545 }
2546 return true;
2547}
2548
2550 StringSet<> UniquePrefixes;
2551 // Add default prefixes to catch user-supplied duplicates of them below.
2552 if (Req.CheckPrefixes.empty())
2553 UniquePrefixes.insert_range(DefaultCheckPrefixes);
2554 if (Req.CommentPrefixes.empty())
2555 UniquePrefixes.insert_range(DefaultCommentPrefixes);
2556 // Do not validate the default prefixes, or diagnostics about duplicates might
2557 // incorrectly indicate that they were supplied by the user.
2558 if (!ValidatePrefixes("check", UniquePrefixes, Req.CheckPrefixes))
2559 return false;
2560 if (!ValidatePrefixes("comment", UniquePrefixes, Req.CommentPrefixes))
2561 return false;
2562 return true;
2563}
2564
2566 ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM) {
2567 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2568 "Overriding defined variable with command-line variable definitions");
2569
2570 if (CmdlineDefines.empty())
2571 return Error::success();
2572
2573 // Create a string representing the vector of command-line definitions. Each
2574 // definition is on its own line and prefixed with a definition number to
2575 // clarify which definition a given diagnostic corresponds to.
2576 unsigned I = 0;
2577 Error Errs = Error::success();
2578 std::string CmdlineDefsDiag;
2579 SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;
2580 for (StringRef CmdlineDef : CmdlineDefines) {
2581 std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
2582 size_t EqIdx = CmdlineDef.find('=');
2583 if (EqIdx == StringRef::npos) {
2584 CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2585 continue;
2586 }
2587 // Numeric variable definition.
2588 if (CmdlineDef[0] == '#') {
2589 // Append a copy of the command-line definition adapted to use the same
2590 // format as in the input file to be able to reuse
2591 // parseNumericSubstitutionBlock.
2592 CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
2593 std::string SubstitutionStr = std::string(CmdlineDef);
2594 SubstitutionStr[EqIdx] = ':';
2595 CmdlineDefsIndices.push_back(
2596 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2597 CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
2598 } else {
2599 CmdlineDefsDiag += DefPrefix;
2600 CmdlineDefsIndices.push_back(
2601 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2602 CmdlineDefsDiag += (CmdlineDef + "\n").str();
2603 }
2604 }
2605
2606 // Create a buffer with fake command line content in order to display
2607 // parsing diagnostic with location information and point to the
2608 // global definition with invalid syntax.
2609 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2610 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");
2611 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2612 SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
2613
2614 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2615 StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
2616 CmdlineDefIndices.second);
2617 if (CmdlineDef.empty()) {
2618 Errs = joinErrors(
2619 std::move(Errs),
2620 ErrorDiagnostic::get(SM, CmdlineDef,
2621 "missing equal sign in global definition"));
2622 continue;
2623 }
2624
2625 // Numeric variable definition.
2626 if (CmdlineDef[0] == '#') {
2627 // Now parse the definition both to check that the syntax is correct and
2628 // to create the necessary class instance.
2629 StringRef CmdlineDefExpr = CmdlineDef.substr(1);
2630 std::optional<NumericVariable *> DefinedNumericVariable;
2631 Expected<std::unique_ptr<Expression>> ExpressionResult =
2633 DefinedNumericVariable, false,
2634 std::nullopt, this, SM);
2635 if (!ExpressionResult) {
2636 Errs = joinErrors(std::move(Errs), ExpressionResult.takeError());
2637 continue;
2638 }
2639 std::unique_ptr<Expression> Expression = std::move(*ExpressionResult);
2640 // Now evaluate the expression whose value this variable should be set
2641 // to, since the expression of a command-line variable definition should
2642 // only use variables defined earlier on the command-line. If not, this
2643 // is an error and we report it.
2645 if (!Value) {
2646 Errs = joinErrors(std::move(Errs), Value.takeError());
2647 continue;
2648 }
2649
2650 assert(DefinedNumericVariable && "No variable defined");
2651 (*DefinedNumericVariable)->setValue(*Value);
2652
2653 // Record this variable definition.
2654 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2655 *DefinedNumericVariable;
2656 } else {
2657 // String variable definition.
2658 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
2659 StringRef CmdlineName = CmdlineNameVal.first;
2660 StringRef OrigCmdlineName = CmdlineName;
2662 Pattern::parseVariable(CmdlineName, SM);
2663 if (!ParseVarResult) {
2664 Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());
2665 continue;
2666 }
2667 // Check that CmdlineName does not denote a pseudo variable is only
2668 // composed of the parsed numeric variable. This catches cases like
2669 // "FOO+2" in a "FOO+2=10" definition.
2670 if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
2671 Errs = joinErrors(std::move(Errs),
2673 SM, OrigCmdlineName,
2674 "invalid name in string variable definition '" +
2675 OrigCmdlineName + "'"));
2676 continue;
2677 }
2678 StringRef Name = ParseVarResult->Name;
2679
2680 // Detect collisions between string and numeric variables when the former
2681 // is created later than the latter.
2682 if (GlobalNumericVariableTable.contains(Name)) {
2683 Errs = joinErrors(std::move(Errs),
2684 ErrorDiagnostic::get(SM, Name,
2685 "numeric variable with name '" +
2686 Name + "' already exists"));
2687 continue;
2688 }
2689 GlobalVariableTable.insert(CmdlineNameVal);
2690 // Mark the string variable as defined to detect collisions between
2691 // string and numeric variables in defineCmdlineVariables when the latter
2692 // is created later than the former. We cannot reuse GlobalVariableTable
2693 // for this by populating it with an empty string since we would then
2694 // lose the ability to detect the use of an undefined variable in
2695 // match().
2696 DefinedVariableTable[Name] = true;
2697 }
2698 }
2699
2700 return Errs;
2701}
2702
2704 SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;
2705 for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)
2706 if (Var.first()[0] != '$')
2707 LocalPatternVars.push_back(Var.first());
2708
2709 // Numeric substitution reads the value of a variable directly, not via
2710 // GlobalNumericVariableTable. Therefore, we clear local variables by
2711 // clearing their value which will lead to a numeric substitution failure. We
2712 // also mark the variable for removal from GlobalNumericVariableTable since
2713 // this is what defineCmdlineVariables checks to decide that no global
2714 // variable has been defined.
2715 for (const auto &Var : GlobalNumericVariableTable)
2716 if (Var.first()[0] != '$') {
2717 Var.getValue()->clearValue();
2718 LocalNumericVars.push_back(Var.first());
2719 }
2720
2721 for (const auto &Var : LocalPatternVars)
2722 GlobalVariableTable.erase(Var);
2723 for (const auto &Var : LocalNumericVars)
2724 GlobalNumericVariableTable.erase(Var);
2725}
2726
2728 std::vector<FileCheckDiag> *Diags) {
2729 bool ChecksFailed = false;
2730
2731 unsigned i = 0, j = 0, e = CheckStrings.size();
2732 while (true) {
2733 StringRef CheckRegion;
2734 if (j == e) {
2735 CheckRegion = Buffer;
2736 } else {
2737 const FileCheckString &CheckLabelStr = CheckStrings[j];
2738 if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
2739 ++j;
2740 continue;
2741 }
2742
2743 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
2744 size_t MatchLabelLen = 0;
2745 size_t MatchLabelPos =
2746 CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
2747 if (MatchLabelPos == StringRef::npos)
2748 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
2749 return false;
2750
2751 CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
2752 Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
2753 ++j;
2754 }
2755
2756 // Do not clear the first region as it's the one before the first
2757 // CHECK-LABEL and it would clear variables defined on the command-line
2758 // before they get used.
2759 if (i != 0 && Req.EnableVarScope)
2760 PatternContext->clearLocalVars();
2761
2762 for (; i != j; ++i) {
2763 const FileCheckString &CheckStr = CheckStrings[i];
2764
2765 // Check each string within the scanned region, including a second check
2766 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
2767 size_t MatchLen = 0;
2768 size_t MatchPos =
2769 CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
2770
2771 if (MatchPos == StringRef::npos) {
2772 ChecksFailed = true;
2773 i = j;
2774 break;
2775 }
2776
2777 CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
2778 }
2779
2780 if (j == e)
2781 break;
2782 }
2783
2784 // Success if no checks failed.
2785 return !ChecksFailed;
2786}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, PrefixMatcher &Matcher, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
static size_t SkipWord(StringRef Str, size_t Loc)
static char popFront(StringRef &S)
constexpr StringLiteral SpaceChars
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, std::vector< FileCheckDiag > *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, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported,...
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 SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy, const SourceMgr &SM, SMLoc Loc, Check::FileCheckType CheckTy, StringRef Buffer, size_t Pos, size_t Len, std::vector< FileCheckDiag > *Diags, bool AdjustPrevDiags=false)
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 Error printMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error or (2) ErrorReported if an error was reported,...
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)
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:1023
APInt abs() const
Get the absolute value.
Definition APInt.h:1804
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1497
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:330
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1939
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1965
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:1971
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:996
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:342
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition APInt.h:1131
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition APInt.cpp:1952
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:2175
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
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:97
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
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 bool checkInput(SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags=nullptr)
Checks the input to FileCheck provided in the Buffer against the expected strings read from the check...
LLVM_ABI ~FileCheck()
LLVM_ABI bool ValidateCheckPrefixes()
A helper class to return the specified delimiter string after the first invocation of operator String...
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.
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags) const
void printSubstitutions(const SourceMgr &SM, StringRef Buffer, SMRange MatchRange, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
Prints the value of successful substitutions.
SMLoc getLoc() const
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, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
static LLVM_ABI_FOR_TEST bool isValidVarNameStart(char C)
int getCount() const
Check::FileCheckType getCheckTy() const
LLVM_ABI_FOR_TEST bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, const FileCheckRequest &Req)
Parses the pattern in PatternStr and initializes this Pattern instance accordingly.
@ Newline
Compile for newline-sensitive matching.
Definition Regex.h:40
@ IgnoreCase
Compile for matching that ignores upper/lower case distinctions.
Definition Regex.h:34
static LLVM_ABI std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
Definition Regex.cpp:239
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition Regex.cpp:83
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
Represents a range in source code.
Definition SMLoc.h:47
SMLoc Start
Definition SMLoc.h:49
SMLoc End
Definition SMLoc.h:49
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition SourceMgr.h:37
LLVM_ABI std::pair< unsigned, unsigned > getLineAndColumn(SMLoc Loc, unsigned BufferID=0) const
Find the line and column number for the specified location in the specified file.
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:864
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:712
static constexpr size_t npos
Definition StringRef.h:57
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition StringRef.h:501
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:261
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:611
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:696
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
char front() const
front - Get the first character in the string.
Definition StringRef.h:149
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:140
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition StringRef.h:802
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:426
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:376
iterator end() const
Definition StringRef.h:114
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
Definition StringRef.h:814
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:582
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:293
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition StringRef.h:826
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:637
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:618
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:45
Class to represent an undefined variable error, which quotes that variable's name when printed.
static LLVM_ABI_FOR_TEST char ID
LLVM Value Representation.
Definition Value.h:75
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ CheckBadNot
Marks when parsing found a -NOT check combined with another CHECK suffix.
Definition FileCheck.h:67
@ CheckBadCount
Marks when parsing found a -COUNT directive with invalid count value.
Definition FileCheck.h:70
@ CheckEOF
Indicates the pattern only matches the end of file.
Definition FileCheck.h:64
@ CheckMisspelled
Definition FileCheck.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
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:990
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition Error.h:967
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:2198
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
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:1744
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:1634
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
constexpr unsigned BitWidth
bool isPrint(char C)
Checks whether character C is printable.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1945
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:1083
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
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.
std::string Note
A note to replace the one normally indicated by MatchTy, or the empty string if none.
Definition FileCheck.h:170
unsigned InputStartCol
Definition FileCheck.h:165
enum llvm::FileCheckDiag::MatchType MatchTy
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
Definition FileCheck.h:164
unsigned InputEndLine
Definition FileCheck.h:166
LLVM_ABI FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange, StringRef Note="")
Check::FileCheckType CheckTy
What is the FileCheck directive for this diagnostic?
Definition FileCheck.h:116
MatchType
What type of match result does this diagnostic describe?
Definition FileCheck.h:131
@ MatchFoundButWrongLine
Indicates a match for an expected pattern, but the match is on the wrong line.
Definition FileCheck.h:138
@ MatchNoneAndExcluded
Indicates no match for an excluded pattern.
Definition FileCheck.h:148
@ MatchFoundButExcluded
Indicates a match for an excluded pattern.
Definition FileCheck.h:135
@ MatchFuzzy
Indicates a fuzzy match that serves as a suggestion for the next intended match for an expected patte...
Definition FileCheck.h:160
@ MatchFoundButDiscarded
Indicates a discarded match for an expected pattern.
Definition FileCheck.h:140
@ MatchNoneForInvalidPattern
Indicates no match due to an expected or excluded pattern that has proven to be invalid at match time...
Definition FileCheck.h:157
@ MatchFoundAndExpected
Indicates a good match for an expected pattern.
Definition FileCheck.h:133
@ MatchNoneButExpected
Indicates no match for an expected pattern, but this might follow good matches when multiple matches ...
Definition FileCheck.h:152
SMLoc CheckLoc
Where is the FileCheck directive for this diagnostic?
Definition FileCheck.h:118
Contains info about various FileCheck options.
Definition FileCheck.h:31
std::vector< StringRef > CommentPrefixes
Definition FileCheck.h:33
std::vector< StringRef > CheckPrefixes
Definition FileCheck.h:32
A check that we found in the input file.
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.
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.
StringRef Prefix
Which prefix name this check matched.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches "dag strings" and their mixed "not strings".
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, size_t &MatchLen, FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches check string and its "not strings" and/or "dag strings".
bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
std::optional< Match > TheMatch
Parsing information about a variable.