52 auto CreatePrecisionRegex = [&](
StringRef S) {
53 return (
Twine(AlternateFormPrefix) + S +
Twine(
'{') +
Twine(Precision) +
61 return CreatePrecisionRegex(
"([1-9][0-9]*)?[0-9]");
62 return std::string(
"[0-9]+");
65 return CreatePrecisionRegex(
"-?([1-9][0-9]*)?[0-9]");
66 return std::string(
"-?[0-9]+");
69 return CreatePrecisionRegex(
"([1-9A-F][0-9A-F]*)?[0-9A-F]");
70 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9A-F]+")).str();
73 return CreatePrecisionRegex(
"([1-9a-f][0-9a-f]*)?[0-9a-f]");
74 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9a-f]+")).str();
77 "trying to match value with invalid format");
87 bool UpperCase =
false;
105 "trying to match value with invalid format");
107 IntValue.
abs().
toString(AbsoluteValueStr, Radix,
false,
113 if (Precision > AbsoluteValueStr.
size()) {
114 unsigned LeadingZeros = Precision - AbsoluteValueStr.
size();
115 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
116 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
120 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
132 APInt Result = AbsVal;
141 bool Negative = StrVal.consume_front(
"-");
143 bool MissingFormPrefix =
144 !ValueIsSigned && AlternateForm && !StrVal.consume_front(
"0x");
145 (void)MissingFormPrefix;
146 assert(!MissingFormPrefix &&
"missing alternate form prefix");
148 [[maybe_unused]]
bool ParseFailure =
149 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
153 assert(!ParseFailure &&
"unable to represent numeric value");
154 return toSigned(ResultValue, Negative);
158 const APInt &RightOperand,
bool &Overflow) {
159 return LeftOperand.
sadd_ov(RightOperand, Overflow);
163 const APInt &RightOperand,
bool &Overflow) {
164 return LeftOperand.
ssub_ov(RightOperand, Overflow);
168 const APInt &RightOperand,
bool &Overflow) {
169 return LeftOperand.
smul_ov(RightOperand, Overflow);
173 const APInt &RightOperand,
bool &Overflow) {
175 if (RightOperand.
isZero())
178 return LeftOperand.
sdiv_ov(RightOperand, Overflow);
182 const APInt &RightOperand,
bool &Overflow) {
184 return LeftOperand.
slt(RightOperand) ? RightOperand : LeftOperand;
188 const APInt &RightOperand,
bool &Overflow) {
190 if (
cantFail(
exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
197 std::optional<APInt>
Value = Variable->getValue();
210 if (!MaybeLeftOp || !MaybeRightOp) {
216 return std::move(Err);
219 APInt LeftOp = *MaybeLeftOp;
220 APInt RightOp = *MaybeRightOp;
225 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
226 LeftOp = LeftOp.
sext(NewBitWidth);
227 RightOp = RightOp.
sext(NewBitWidth);
237 LeftOp = LeftOp.
sext(NewBitWidth);
238 RightOp = RightOp.
sext(NewBitWidth);
246 if (!LeftFormat || !RightFormat) {
252 return std::move(Err);
257 *LeftFormat != *RightFormat)
260 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
261 "' (" + LeftFormat->toString() +
") and '" +
262 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
263 "), need an explicit format specifier");
270 assert(ExpressionPointer->getAST() !=
nullptr &&
271 "Substituting empty expression");
276 return Format.getMatchingString(*EvaluatedValue);
287 return "\"" + std::move(*
Literal) +
"\"";
304 Result.reserve(VarVal->size() + 2);
315 const bool NeedsEscaping =
323 OS <<
" (escaped value)";
336 bool IsPseudo = Str[0] ==
'@';
339 if (Str[0] ==
'$' || IsPseudo)
345 (IsPseudo ?
"pseudo " :
"global ") +
351 for (
size_t E = Str.size();
I != E; ++
I)
382 Expected<VariableProperties> ParseVarResult =
parseVariable(Expr, SM);
385 StringRef
Name = ParseVarResult->Name;
387 if (ParseVarResult->IsPseudo)
389 SM, Name,
"definition of pseudo numeric variable unsupported");
393 if (Context->DefinedVariableTable.contains(Name))
395 SM, Name,
"string variable with name '" + Name +
"' already exists");
400 SM, Expr,
"unexpected characters after numeric variable name");
402 NumericVariable *DefinedNumericVariable;
403 auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
404 if (VarTableIter != Context->GlobalNumericVariableTable.end()) {
405 DefinedNumericVariable = VarTableIter->second;
408 SM, Expr,
"format different from previous variable definition");
410 DefinedNumericVariable =
411 Context->makeNumericVariable(Name, ImplicitFormat, LineNumber);
413 return DefinedNumericVariable;
417 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
419 if (IsPseudo && Name !=
"@LINE")
421 SM, Name,
"invalid pseudo numeric variable '" + Name +
"'");
432 Context->GlobalNumericVariableTable.try_emplace(Name);
434 VarTableIter->second = Context->makeNumericVariable(
436 NumericVariable *NumericVariable = VarTableIter->second;
439 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
442 "numeric variable '" + Name +
443 "' defined earlier in the same CHECK directive");
445 return std::make_unique<NumericVariableUse>(Name, NumericVariable);
449 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
453 if (AO != AllowedOperand::Any)
455 SM, Expr,
"parenthesized expression not permitted here");
456 return parseParenExpr(Expr, LineNumber, Context, SM);
459 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
461 Expected<Pattern::VariableProperties> ParseVarResult =
463 if (ParseVarResult) {
466 if (AO != AllowedOperand::Any)
468 "unexpected function call");
470 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
474 return parseNumericVariableUse(ParseVarResult->Name,
475 ParseVarResult->IsPseudo, LineNumber,
479 if (AO == AllowedOperand::LineVar)
487 StringRef SaveExpr = Expr;
489 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
492 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
498 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
503Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
515 Expected<std::unique_ptr<ExpressionAST>> SubExprResult = parseNumericOperand(
516 Expr, AllowedOperand::Any,
false, LineNumber,
520 StringRef OrigExpr = Expr;
521 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
522 LineNumber, Context, SM);
526 return SubExprResult;
530 "missing ')' at end of nested expression");
532 return SubExprResult;
537 std::unique_ptr<ExpressionAST> LeftOp,
538 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
541 if (RemainingExpr.
empty())
542 return std::move(LeftOp);
558 SM, OpLoc, Twine(
"unsupported operation '") + Twine(Operator) +
"'");
563 if (RemainingExpr.
empty())
565 "missing operand in expression");
568 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
569 Expected<std::unique_ptr<ExpressionAST>> RightOpResult =
570 parseNumericOperand(RemainingExpr, AO,
false,
571 LineNumber, Context, SM);
573 return RightOpResult;
576 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
577 std::move(*RightOpResult));
582 std::optional<size_t> LineNumber,
587 auto OptFunc = StringSwitch<binop_eval_t>(FuncName)
598 SM, FuncName, Twine(
"call to undefined function '") + FuncName +
"'");
610 StringRef OuterBinOpExpr = Expr;
611 Expected<std::unique_ptr<ExpressionAST>> Arg = parseNumericOperand(
612 Expr, AllowedOperand::Any,
false, LineNumber,
614 while (Arg && !Expr.
empty()) {
621 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg),
false, LineNumber,
628 Args.push_back(std::move(*Arg));
642 "missing ')' at end of call expression");
644 const unsigned NumArgs =
Args.size();
646 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
651 Twine(
"function '") + FuncName +
652 Twine(
"' takes 2 arguments but ") +
653 Twine(NumArgs) +
" given");
657 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
658 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
660 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
662 DefinedNumericVariable = std::nullopt;
664 unsigned Precision = 0;
667 size_t FormatSpecEnd = Expr.
find(
',');
668 size_t FunctionStart = Expr.
find(
'(');
669 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
676 "invalid matching format specification in expression");
686 "invalid precision in format specifier");
689 if (!FormatExpr.
empty()) {
704 Precision, AlternateForm);
708 Precision, AlternateForm);
712 "invalid format specifier in expression");
719 SM, AlternateFormFlagLoc,
720 "alternate form only supported for hex values");
723 if (!FormatExpr.
empty())
726 "invalid matching format specification in expression");
730 size_t DefEnd = Expr.
find(
':');
732 DefExpr = Expr.
substr(0, DefEnd);
733 Expr = Expr.
substr(DefEnd + 1);
743 if (HasParsedValidConstraint)
745 SM, Expr,
"empty numeric expression should not have a constraint");
752 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
754 Expr, AO, !HasParsedValidConstraint, LineNumber, Context, SM);
757 IsLegacyLineExpr, LineNumber, Context, SM);
762 "unexpected characters at end of expression '" + Expr +
"'");
776 else if (ExpressionASTPointer) {
778 ExpressionASTPointer->getImplicitFormat(SM);
786 std::unique_ptr<Expression> ExpressionPointer =
787 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
793 DefExpr, Context, LineNumber, ExpressionPointer->getFormat(), SM);
800 return std::move(ExpressionPointer);
812 PatternStr = PatternStr.
rtrim(
" \t");
817 "found empty check string with prefix '" + Prefix +
":'");
824 "found non-empty check string for empty check with prefix '" + Prefix +
835 if (CheckTy.isLiteralMatch()) {
836 FixedStr = PatternStr;
841 if (!MatchFullLinesHere &&
842 (PatternStr.
size() < 2 ||
844 FixedStr = PatternStr;
848 if (MatchFullLinesHere) {
856 unsigned CurParen = 1;
860 while (!PatternStr.
empty()) {
864 size_t End = PatternStr.
find(
"}}");
868 "found start of regex string with no end '}}'");
876 bool HasAlternation = PatternStr.
contains(
'|');
877 if (HasAlternation) {
882 if (AddRegExToRegEx(PatternStr.
substr(2, End - 2), CurParen, SM))
887 PatternStr = PatternStr.
substr(End + 2);
905 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
912 "Invalid substitution block, no ]] found");
918 PatternStr = UnparsedPatternStr.
substr(End + 2);
920 bool IsDefinition =
false;
921 bool SubstNeeded =
false;
924 bool IsLegacyLineExpr =
false;
928 std::string WildcardRegexp;
929 size_t SubstInsertIdx = RegExStr.
size();
933 size_t VarEndIdx = MatchStr.
find(
':');
945 if (!ParseVarResult) {
950 bool IsPseudo = ParseVarResult->IsPseudo;
953 SubstNeeded = !IsDefinition;
958 "invalid name in string variable definition");
964 if (Context->GlobalNumericVariableTable.contains(Name)) {
967 "numeric variable with name '" + Name +
"' already exists");
971 MatchRegexp = MatchStr;
974 MatchStr = OrigMatchStr;
975 IsLegacyLineExpr = IsNumBlock =
true;
977 if (!MatchStr.
empty()) {
980 "invalid name in string variable use");
989 std::unique_ptr<Expression> ExpressionPointer;
990 std::optional<NumericVariable *> DefinedNumericVariable;
994 IsLegacyLineExpr, LineNumber, Context,
1001 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
1002 if (DefinedNumericVariable) {
1003 IsDefinition =
true;
1004 DefName = (*DefinedNumericVariable)->getName();
1007 SubstStr = MatchStr;
1011 MatchRegexp = WildcardRegexp;
1021 NumericVariableMatch NumericVariableDefinition = {
1022 *DefinedNumericVariable, CurParen};
1023 NumericVariableDefs[DefName] = NumericVariableDefinition;
1028 Context->GlobalNumericVariableTable[DefName] =
1029 *DefinedNumericVariable;
1031 VariableDefs[DefName] = CurParen;
1038 Context->DefinedVariableTable[DefName] =
true;
1044 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
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 " +
1066 AddBackrefToRegEx(CaptureParenGroup);
1072 ? Context->makeNumericSubstitution(
1073 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1074 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1084 size_t FixedMatchEnd =
1085 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1087 PatternStr = PatternStr.
substr(FixedMatchEnd);
1090 if (MatchFullLinesHere) {
1102 if (!R.isValid(
Error)) {
1104 "invalid regex: " +
Error);
1108 RegExStr += RS.str();
1109 CurParen += R.getNumMatches();
1113void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1115 "Invalid backref number");
1116 std::string Backref;
1117 if (BackrefNum >= 1 && BackrefNum <= 9)
1118 Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1120 Backref = std::string(
"\\g{") + std::to_string(BackrefNum) +
'}';
1122 RegExStr += Backref;
1132 if (!FixedStr.empty()) {
1146 if (!Substitutions.empty()) {
1149 Context->LineVariable->setValue(
1150 APInt(
sizeof(*LineNumber) * 8, *LineNumber));
1152 size_t InsertOffset = 0;
1168 return ErrorDiagnostic::get(
1169 SM, Substitution->getFromString(),
1170 "unable to substitute variable or "
1171 "numeric expression: overflow error");
1174 return ErrorDiagnostic::get(SM, E.getVarName(),
1183 InsertOffset +=
Value->size();
1186 return std::move(Errs);
1189 RegExToMatch = TmpStr;
1196 if (!
Regex(RegExToMatch, Flags).
match(Buffer, &MatchInfo))
1200 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1204 for (
const auto &VariableDef : VariableDefs) {
1205 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1206 Context->GlobalVariableTable[VariableDef.first] =
1207 MatchInfo[VariableDef.second];
1215 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1216 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
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");
1225 NumericVariableMatch.DefinedNumericVariable;
1227 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1236 Context->GlobalNumericVariableTable.try_emplace(NumericVariableDef.getKey(),
1237 DefinedNumericVariable);
1244unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1252 if (ExampleString.empty())
1253 ExampleString = RegExStr;
1257 BufferPrefix = BufferPrefix.
split(
'\n').first;
1264 std::vector<FileCheckDiag> *Diags)
const {
1266 if (!Substitutions.empty()) {
1274 if (!MatchedValue) {
1281 OS << *MatchedValue;
1288 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1298 std::vector<FileCheckDiag> *Diags)
const {
1299 if (VariableDefs.empty() && NumericVariableDefs.empty())
1307 for (
const auto &VariableDef : VariableDefs) {
1309 VC.Name = VariableDef.first;
1313 VC.Range =
SMRange(Start, End);
1316 for (
const auto &VariableDef : NumericVariableDefs) {
1318 VC.Name = VariableDef.getKey();
1319 std::optional<StringRef> StrValue =
1320 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1325 VC.Range =
SMRange(Start, End);
1330 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1333 assert(
A.Range.Start !=
B.Range.Start &&
1334 "unexpected overlapping variable captures");
1335 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1338 for (
const VarCapture &VC : VarCaptures) {
1341 OS <<
"captured var \"" << VC.Name <<
"\"";
1343 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range, OS.
str());
1352 StringRef Buffer,
size_t Pos,
size_t Len,
1353 std::vector<FileCheckDiag> *Diags,
1354 bool AdjustPrevDiags =
false) {
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;
1365 Diags->emplace_back(SM, CheckTy,
Loc, MatchTy,
Range);
1371 std::vector<FileCheckDiag> *Diags)
const {
1376 size_t NumLinesForward = 0;
1378 double BestQuality = 0;
1381 if (
size_t(4096) *
size_t(2048) <
1382 std::min(
size_t(4096), Buffer.
size()) *
1383 std::max(FixedStr.size(), RegExStr.size()))
1387 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1388 if (Buffer[i] ==
'\n')
1393 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1398 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1399 double Quality = Distance + (NumLinesForward / 100.);
1403 BestQuality = Quality;
1415 "possible intended match here");
1424 auto VarIter = GlobalVariableTable.find(VarName);
1425 if (VarIter == GlobalVariableTable.end())
1428 return VarIter->second;
1431template <
class... Types>
1433 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1434 return NumericVariables.back().get();
1438FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1440 Substitutions.push_back(
1441 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1442 return Substitutions.back().get();
1445Substitution *FileCheckPatternContext::makeNumericSubstitution(
1448 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1449 this, ExpressionStr, std::move(Expression), InsertIdx));
1450 return Substitutions.back().get();
1457 size_t BracketDepth = 0;
1459 while (!Str.empty()) {
1460 if (Str.starts_with(
"]]") && BracketDepth == 0)
1462 if (Str[0] ==
'\\') {
1464 Str = Str.substr(2);
1474 if (BracketDepth == 0) {
1477 "missing closing \"]\" for regex variable");
1483 Str = Str.substr(1);
1496 Ptr != End; ++Ptr) {
1498 if (Ptr <= End - 2 && Ptr[0] ==
'\r' && Ptr[1] ==
'\n') {
1504 if (Req.NoCanonicalizeWhiteSpace || (*Ptr !=
' ' && *Ptr !=
'\t')) {
1511 while (Ptr + 1 != End && (Ptr[1] ==
' ' || Ptr[1] ==
'\t'))
1534 return (
isAlnum(c) || c ==
'-' || c ==
'_');
1538 assert(Count > 0 &&
"zero and negative counts are not supported");
1540 "count supported only for plain CHECK directives");
1546 if (Modifiers.none())
1559 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1567 return "misspelled";
1570 return WithModifiers(
"-COUNT");
1571 return WithModifiers(
"");
1573 return WithModifiers(
"-NEXT");
1575 return WithModifiers(
"-SAME");
1577 return WithModifiers(
"-NOT");
1579 return WithModifiers(
"-DAG");
1581 return WithModifiers(
"-LABEL");
1583 return WithModifiers(
"-EMPTY");
1585 return std::string(Prefix);
1587 return "implicit EOF";
1596static std::pair<Check::FileCheckType, StringRef>
1599 if (Buffer.
size() <= Prefix.size())
1612 -> std::pair<Check::FileCheckType, StringRef> {
1621 Rest = Rest.
ltrim();
1623 Ret.setLiteralMatch();
1627 Rest = Rest.
ltrim();
1637 if (Rest.
front() ==
'{')
1652 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1654 return ConsumeModifiers(
1686static std::pair<Check::FileCheckType, StringRef>
1688 bool Misspelled =
false;
1723 Prefixes.push_back({Prefix, Input.find(Prefix)});
1725 Prefixes.push_back({Prefix, Input.find(Prefix)});
1729 [](
auto A,
auto B) { return A.first.size() > B.first.size(); });
1737 "Buffer must be suffix of Input");
1739 size_t From = Buffer.
data() -
Input.data();
1741 for (
auto &[Prefix, Pos] :
Prefixes) {
1744 Pos =
Input.find(Prefix, From);
1777static std::pair<StringRef, StringRef>
1779 StringRef &Buffer,
unsigned &LineNumber,
1781 while (!Buffer.
empty()) {
1783 StringRef Prefix = Matcher.match(Buffer);
1789 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1790 "Prefix doesn't start inside of buffer!");
1791 size_t Loc = Prefix.data() - Buffer.
data();
1794 LineNumber += Skipped.count(
'\n');
1801 if (Skipped.empty() || !
IsPartOfWord(Skipped.back())) {
1804 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1808 return {Prefix, AfterSuffix};
1822 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1824 LineVariable = makeNumericVariable(
1826 GlobalNumericVariableTable[LineName] = LineVariable;
1836 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1837 if (ImpPatBufferIDRange)
1838 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1841 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1847 PatternContext->createLineVariable();
1849 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1850 for (
StringRef PatternString : Req.ImplicitCheckNot) {
1853 std::string Prefix =
"-implicit-check-not='";
1854 std::string Suffix =
"'";
1856 (Prefix + PatternString + Suffix).str(),
"command line");
1859 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1861 if (ImpPatBufferIDRange) {
1862 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1863 ImpPatBufferIDRange->first = BufferID;
1864 ImpPatBufferIDRange->second = BufferID + 1;
1866 assert(BufferID == ImpPatBufferIDRange->second &&
1867 "expected consecutive source buffer IDs");
1868 ++ImpPatBufferIDRange->second;
1872 ImplicitNegativeChecks.emplace_back(
1875 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1876 PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
1879 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1880 ImplicitNegativeChecks;
1883 unsigned LineNumber = 1;
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();
1896 std::tie(UsedPrefix, AfterSuffix) =
1898 if (UsedPrefix.
empty())
1901 PrefixesNotFound.erase(UsedPrefix);
1904 "Failed to move Buffer's start forward, or pointed prefix outside "
1908 "Parsing after suffix doesn't start inside of buffer!");
1911 const char *UsedPrefixStart = UsedPrefix.
data();
1921 AfterSuffix.
data() - UsedPrefix.
data());
1924 "misspelled directive '" + UsedDirective +
"'");
1931 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1938 "invalid count in -COUNT specification on prefix '" +
1945 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1956 Buffer = Buffer.
substr(EOL);
1963 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1964 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1971 "found '" + UsedPrefix +
"-LABEL:'"
1972 " with variable definition or use");
1979 CheckStrings.empty()) {
1985 "found '" + UsedPrefix +
"-" +
Type +
1986 "' without previous '" + UsedPrefix +
": line");
1992 DagNotMatches.emplace_back(
P, UsedPrefix);
1997 CheckStrings.emplace_back(std::move(
P), UsedPrefix, PatternLoc,
1998 std::move(DagNotMatches));
1999 DagNotMatches = ImplicitNegativeChecks;
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 " :
" ");
2012 for (
StringRef MissingPrefix : PrefixesNotFound)
2013 errs() << LS <<
"\'" << MissingPrefix <<
":'";
2020 if (!DagNotMatches.empty()) {
2021 CheckStrings.emplace_back(
2024 std::move(DagNotMatches));
2037 std::vector<FileCheckDiag> *Diags) {
2039 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2040 bool PrintDiag =
true;
2064 assert(!HasError &&
"expected to report more diagnostics for error");
2069 std::string Message =
formatv(
"{0}: {1} string found in input",
2071 (ExpectedMatch ?
"expected" :
"excluded"))
2074 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2091 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2092 FileCheckDiag::MatchFoundErrorNote,
2093 E.getRange(), E.getMessage().str());
2105 bool VerboseVerbose,
2106 std::vector<FileCheckDiag> *Diags) {
2108 bool HasError = ExpectedMatch;
2109 bool HasPatternError =
false;
2115 std::move(MatchError),
2117 HasError = HasPatternError =
true;
2127 bool PrintDiag =
true;
2129 if (!VerboseVerbose)
2145 Buffer, 0, Buffer.
size(), Diags);
2149 Diags->emplace_back(SM, Pat.
getCheckTy(),
Loc, MatchTy, NoteRange,
2154 assert(!HasError &&
"expected to report more diagnostics for error");
2160 if (!HasPatternError) {
2161 std::string Message =
formatv(
"{0}: {1} string not found in input",
2163 (ExpectedMatch ?
"expected" :
"excluded"))
2172 "scanning from here");
2190 std::vector<FileCheckDiag> *Diags) {
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,
2201 const char *&FirstNewLine) {
2202 unsigned NumNewLines = 0;
2217 if (NumNewLines == 1)
2218 FirstNewLine =
Range.begin();
2223 bool IsLabelScanMode,
size_t &MatchLen,
2225 std::vector<FileCheckDiag> *Diags)
const {
2227 std::vector<const DagNotPrefixInfo *> NotStrings;
2233 if (!IsLabelScanMode) {
2235 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2241 size_t LastMatchEnd = LastPos;
2242 size_t FirstMatchPos = 0;
2245 assert(
Pat.getCount() != 0 &&
"pattern count can not be zero");
2246 for (
int i = 1; i <=
Pat.getCount(); i++) {
2253 Pat, i, MatchBuffer,
2254 std::move(MatchResult), Req, Diags)) {
2259 size_t MatchPos = MatchResult.
TheMatch->Pos;
2261 FirstMatchPos = LastPos + MatchPos;
2264 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2267 MatchLen = LastMatchEnd - FirstMatchPos;
2271 if (!IsLabelScanMode) {
2272 size_t MatchPos = FirstMatchPos - LastPos;
2280 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2289 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2296 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2300 return FirstMatchPos;
2313 const char *FirstNewLine =
nullptr;
2316 if (NumNewLines == 0) {
2318 CheckName +
": is on the same line as previous match");
2320 "'next' match was here");
2322 "previous match ended here");
2326 if (NumNewLines != 1) {
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");
2347 const char *FirstNewLine =
nullptr;
2350 if (NumNewLines != 0) {
2353 "-SAME: is not on the same line as the previous match");
2355 "'next' match was here");
2357 "previous match ended here");
2366 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2368 bool DirectiveFail =
false;
2369 for (
auto NotInfo : NotStrings) {
2371 "Expect CHECK-NOT!");
2374 false, SM, NotInfo->DagNotPrefix,
2375 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2376 std::move(MatchResult), Req, Diags)) {
2378 DirectiveFail =
true;
2382 return DirectiveFail;
2387 std::vector<const DagNotPrefixInfo *> &NotStrings,
2389 std::vector<FileCheckDiag> *Diags)
const {
2394 size_t StartPos = 0;
2403 std::list<MatchRange> MatchRanges;
2408 PatItr != PatEnd; ++PatItr) {
2410 const StringRef DNPrefix = PatItr->DagNotPrefix;
2413 "Invalid CHECK-DAG or CHECK-NOT!");
2416 NotStrings.push_back(&*PatItr);
2423 size_t MatchLen = 0, MatchPos = StartPos;
2427 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2434 Pat.getLoc(),
Pat, 1, MatchBuffer,
2435 std::move(MatchResult), Req, Diags)) {
2441 MatchLen = MatchResult.
TheMatch->Len;
2444 MatchPos += MatchResult.
TheMatch->Pos;
2445 MatchRange M{MatchPos, MatchPos + MatchLen};
2450 if (MatchRanges.empty())
2451 MatchRanges.insert(MatchRanges.end(), M);
2453 auto Block = MatchRanges.begin();
2460 bool Overlap =
false;
2461 for (;
MI != ME; ++
MI) {
2462 if (M.Pos <
MI->End) {
2465 Overlap =
MI->Pos < M.End;
2471 MatchRanges.insert(
MI, M);
2481 SMRange OldRange(OldStart, OldEnd);
2483 "match discarded, overlaps earlier DAG match here",
2486 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2487 for (
auto I = Diags->rbegin(), E = Diags->rend();
2488 I != E &&
I->CheckLoc == CheckLoc; ++
I)
2496 true, SM, DNPrefix,
Pat.getLoc(),
Pat, 1, Buffer,
2501 if (std::next(PatItr) == PatEnd ||
2503 if (!NotStrings.empty()) {
2508 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2509 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2516 StartPos = MatchRanges.rbegin()->End;
2518 MatchRanges.clear();
2527 for (
StringRef Prefix : SuppliedPrefixes) {
2528 if (Prefix.empty()) {
2529 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
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";
2540 if (!UniquePrefixes.
insert(Prefix).second) {
2541 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2542 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2552 if (Req.CheckPrefixes.empty())
2554 if (Req.CommentPrefixes.empty())
2567 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2568 "Overriding defined variable with command-line variable definitions");
2570 if (CmdlineDefines.
empty())
2578 std::string CmdlineDefsDiag;
2580 for (
StringRef CmdlineDef : CmdlineDefines) {
2581 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2582 size_t EqIdx = CmdlineDef.find(
'=');
2584 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2588 if (CmdlineDef[0] ==
'#') {
2592 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2593 std::string SubstitutionStr = std::string(CmdlineDef);
2594 SubstitutionStr[EqIdx] =
':';
2596 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2597 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2599 CmdlineDefsDiag += DefPrefix;
2601 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2602 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2609 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2611 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2614 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2615 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2616 CmdlineDefIndices.second);
2617 if (CmdlineDef.
empty()) {
2621 "missing equal sign in global definition"));
2626 if (CmdlineDef[0] ==
'#') {
2630 std::optional<NumericVariable *> DefinedNumericVariable;
2633 DefinedNumericVariable,
false,
2634 std::nullopt,
this, SM);
2635 if (!ExpressionResult) {
2639 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2650 assert(DefinedNumericVariable &&
"No variable defined");
2651 (*DefinedNumericVariable)->setValue(*
Value);
2654 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2655 *DefinedNumericVariable;
2658 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2659 StringRef CmdlineName = CmdlineNameVal.first;
2660 StringRef OrigCmdlineName = CmdlineName;
2663 if (!ParseVarResult) {
2670 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2673 SM, OrigCmdlineName,
2674 "invalid name in string variable definition '" +
2675 OrigCmdlineName +
"'"));
2682 if (GlobalNumericVariableTable.contains(Name)) {
2685 "numeric variable with name '" +
2686 Name +
"' already exists"));
2689 GlobalVariableTable.insert(CmdlineNameVal);
2696 DefinedVariableTable[Name] =
true;
2706 if (Var.first()[0] !=
'$')
2707 LocalPatternVars.
push_back(Var.first());
2715 for (
const auto &Var : GlobalNumericVariableTable)
2716 if (Var.first()[0] !=
'$') {
2717 Var.getValue()->clearValue();
2718 LocalNumericVars.
push_back(Var.first());
2721 for (
const auto &Var : LocalPatternVars)
2722 GlobalVariableTable.erase(Var);
2723 for (
const auto &Var : LocalNumericVars)
2724 GlobalNumericVariableTable.erase(Var);
2728 std::vector<FileCheckDiag> *Diags) {
2729 bool ChecksFailed =
false;
2731 unsigned i = 0, j = 0, e = CheckStrings.size();
2735 CheckRegion = Buffer;
2744 size_t MatchLabelLen = 0;
2745 size_t MatchLabelPos =
2746 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2751 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2752 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2759 if (i != 0 && Req.EnableVarScope)
2760 PatternContext->clearLocalVars();
2762 for (; i != j; ++i) {
2767 size_t MatchLen = 0;
2769 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2772 ChecksFailed =
true;
2777 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2785 return !ChecksFailed;
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
static bool IsPartOfWord(char c)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
APInt abs() const
Get the absolute value.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
static constexpr unsigned APINT_BITS_PER_WORD
Bits in a word.
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
bool slt(const APInt &RHS) const
Signed less than comparison.
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
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
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.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
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 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.
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)
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.
@ IgnoreCase
Compile for matching that ignores upper/lower case distinctions.
static LLVM_ABI std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
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.
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.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
static constexpr size_t npos
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
LLVM_ABI unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
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.
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
LLVM_ABI size_t find_insensitive(char C, size_t From=0) const
Search for the first character C in the string, ignoring case.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
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.
void insert_range(Range &&R)
std::pair< typename Base::iterator, bool > insert(StringRef key)
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
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...
The instances of the Type class are immutable: once they are created, they are never changed.
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.
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.
@ CheckBadNot
Marks when parsing found a -NOT check combined with another CHECK suffix.
@ CheckBadCount
Marks when parsing found a -COUNT directive with invalid count value.
@ CheckEOF
Indicates the pattern only matches the end of file.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
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.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
FunctionAddr VTableAddr Count
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.
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.
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.
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.
Implement std::hash so that hash_code can be used in STL containers.
StringRef match(StringRef Buffer)
Find the next match of a prefix in Buffer.
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)
std::string Note
A note to replace the one normally indicated by MatchTy, or the empty string if none.
enum llvm::FileCheckDiag::MatchType MatchTy
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
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?
MatchType
What type of match result does this diagnostic describe?
@ MatchFoundButWrongLine
Indicates a match for an expected pattern, but the match is on the wrong line.
@ MatchNoneAndExcluded
Indicates no match for an excluded pattern.
@ MatchFoundButExcluded
Indicates a match for an excluded pattern.
@ MatchFuzzy
Indicates a fuzzy match that serves as a suggestion for the next intended match for an expected patte...
@ MatchFoundButDiscarded
Indicates a discarded match for an expected pattern.
@ MatchNoneForInvalidPattern
Indicates no match due to an expected or excluded pattern that has proven to be invalid at match time...
@ MatchFoundAndExpected
Indicates a good match for an expected pattern.
@ MatchNoneButExpected
Indicates no match for an expected pattern, but this might follow good matches when multiple matches ...
SMLoc CheckLoc
Where is the FileCheck directive for this diagnostic?
Contains info about various FileCheck options.
bool IsDefaultCheckPrefix
bool NoCanonicalizeWhiteSpace
std::vector< StringRef > CommentPrefixes
std::vector< StringRef > CheckPrefixes
bool AllowDeprecatedDagOverlap
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.