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)
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;
1265 if (!Substitutions.empty()) {
1273 if (!MatchedValue) {
1280 OS << *MatchedValue;
1297 if (VariableDefs.empty() && NumericVariableDefs.empty())
1305 for (
const auto &VariableDef : VariableDefs) {
1307 VC.Name = VariableDef.first;
1311 VC.Range =
SMRange(Start, End);
1314 for (
const auto &VariableDef : NumericVariableDefs) {
1316 VC.Name = VariableDef.getKey();
1317 std::optional<StringRef> StrValue =
1318 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1323 VC.Range =
SMRange(Start, End);
1328 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1331 assert(
A.Range.Start !=
B.Range.Start &&
1332 "unexpected overlapping variable captures");
1333 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1336 for (
const VarCapture &VC : VarCaptures) {
1339 OS <<
"captured var \"" << VC.Name <<
"\"";
1363 size_t NumLinesForward = 0;
1365 double BestQuality = 0;
1368 if (
size_t(4096) *
size_t(2048) <
1369 std::min(
size_t(4096), Buffer.
size()) *
1370 std::max(FixedStr.size(), RegExStr.size()))
1374 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1375 if (Buffer[i] ==
'\n')
1380 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1385 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1386 double Quality = Distance + (NumLinesForward / 100.);
1390 BestQuality = Quality;
1402 "possible intended match here");
1411 auto VarIter = GlobalVariableTable.find(VarName);
1412 if (VarIter == GlobalVariableTable.end())
1415 return VarIter->second;
1418template <
class... Types>
1420 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1421 return NumericVariables.back().get();
1425FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1427 Substitutions.push_back(
1428 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1429 return Substitutions.back().get();
1432Substitution *FileCheckPatternContext::makeNumericSubstitution(
1435 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1436 this, ExpressionStr, std::move(Expression), InsertIdx));
1437 return Substitutions.back().get();
1444 size_t BracketDepth = 0;
1446 while (!Str.empty()) {
1447 if (Str.starts_with(
"]]") && BracketDepth == 0)
1449 if (Str[0] ==
'\\') {
1451 Str = Str.substr(2);
1461 if (BracketDepth == 0) {
1464 "missing closing \"]\" for regex variable");
1470 Str = Str.substr(1);
1483 Ptr != End; ++Ptr) {
1485 if (Ptr <= End - 2 && Ptr[0] ==
'\r' && Ptr[1] ==
'\n') {
1491 if (Req.NoCanonicalizeWhiteSpace || (*Ptr !=
' ' && *Ptr !=
'\t')) {
1498 while (Ptr + 1 != End && (Ptr[1] ==
' ' || Ptr[1] ==
'\t'))
1512 return (
isAlnum(c) || c ==
'-' || c ==
'_');
1516 assert(Count > 0 &&
"zero and negative counts are not supported");
1518 "count supported only for plain CHECK directives");
1524 if (Modifiers.none())
1537 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1545 return "misspelled";
1548 return WithModifiers(
"-COUNT");
1549 return WithModifiers(
"");
1551 return WithModifiers(
"-NEXT");
1553 return WithModifiers(
"-SAME");
1555 return WithModifiers(
"-NOT");
1557 return WithModifiers(
"-DAG");
1559 return WithModifiers(
"-LABEL");
1561 return WithModifiers(
"-EMPTY");
1563 return std::string(Prefix);
1565 return "implicit EOF";
1574static std::pair<Check::FileCheckType, StringRef>
1577 if (Buffer.
size() <= Prefix.size())
1590 -> std::pair<Check::FileCheckType, StringRef> {
1599 Rest = Rest.
ltrim();
1601 Ret.setLiteralMatch();
1605 Rest = Rest.
ltrim();
1615 if (Rest.
front() ==
'{')
1630 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1632 return ConsumeModifiers(
1664static std::pair<Check::FileCheckType, StringRef>
1666 bool Misspelled =
false;
1701 Prefixes.push_back({Prefix, Input.find(Prefix)});
1703 Prefixes.push_back({Prefix, Input.find(Prefix)});
1707 [](
auto A,
auto B) { return A.first.size() > B.first.size(); });
1715 "Buffer must be suffix of Input");
1717 size_t From = Buffer.
data() -
Input.data();
1719 for (
auto &[Prefix, Pos] :
Prefixes) {
1722 Pos =
Input.find(Prefix, From);
1755static std::pair<StringRef, StringRef>
1757 StringRef &Buffer,
unsigned &LineNumber,
1759 while (!Buffer.
empty()) {
1761 StringRef Prefix = Matcher.match(Buffer);
1767 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1768 "Prefix doesn't start inside of buffer!");
1769 size_t Loc = Prefix.data() - Buffer.
data();
1772 LineNumber += Skipped.count(
'\n');
1779 if (Skipped.empty() || !
IsPartOfWord(Skipped.back())) {
1782 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1786 return {Prefix, AfterSuffix};
1800 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1802 LineVariable = makeNumericVariable(
1804 GlobalNumericVariableTable[LineName] = LineVariable;
1814 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1815 if (ImpPatBufferIDRange)
1816 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1819 PatternContext->defineCmdlineVariables(Req.GlobalDefines,
SM);
1825 PatternContext->createLineVariable();
1827 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1828 for (
StringRef PatternString : Req.ImplicitCheckNot) {
1831 std::string Prefix =
"-implicit-check-not='";
1832 std::string Suffix =
"'";
1834 (Prefix + PatternString + Suffix).str(),
"command line");
1837 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1838 unsigned BufferID =
SM.AddNewSourceBuffer(std::move(CmdLine),
SMLoc());
1839 if (ImpPatBufferIDRange) {
1840 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1841 ImpPatBufferIDRange->first = BufferID;
1842 ImpPatBufferIDRange->second = BufferID + 1;
1844 assert(BufferID == ImpPatBufferIDRange->second &&
1845 "expected consecutive source buffer IDs");
1846 ++ImpPatBufferIDRange->second;
1850 ImplicitNegativeChecks.emplace_back(
1853 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1854 PatternInBuffer,
"IMPLICIT-CHECK",
SM, Req);
1857 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1858 ImplicitNegativeChecks;
1861 unsigned LineNumber = 1;
1864 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1865 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1866 Req.CheckPrefixes.end());
1867 const size_t DistinctPrefixes = PrefixesNotFound.size();
1874 std::tie(UsedPrefix, AfterSuffix) =
1876 if (UsedPrefix.
empty())
1879 PrefixesNotFound.erase(UsedPrefix);
1882 "Failed to move Buffer's start forward, or pointed prefix outside "
1885 [[maybe_unused]]
const char *BufferEnd = Buffer.
data() + Buffer.
size();
1887 AfterSuffix.
data() <= BufferEnd &&
1888 "Parsing after suffix doesn't start inside of buffer!");
1891 Buffer = AfterSuffix;
1894 const char *UsedPrefixStart = UsedPrefix.
data();
1899 AfterSuffix.
data() - UsedPrefix.
data());
1902 "misspelled directive '" + UsedDirective +
"'");
1909 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1916 "invalid count in -COUNT specification on prefix '" +
1923 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1934 Buffer = Buffer.
substr(EOL);
1941 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1942 if (
P.parsePattern(PatternBuffer, UsedPrefix,
SM, Req))
1949 "found '" + UsedPrefix +
"-LABEL:'"
1950 " with variable definition or use");
1957 CheckStrings.empty()) {
1963 "found '" + UsedPrefix +
"-" +
Type +
1964 "' without previous '" + UsedPrefix +
": line");
1970 DagNotMatches.emplace_back(
P, UsedPrefix);
1975 CheckStrings.emplace_back(std::move(
P), UsedPrefix, PatternLoc,
1976 std::move(DagNotMatches));
1977 DagNotMatches = ImplicitNegativeChecks;
1982 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1983 const bool SomePrefixesUnexpectedlyNotUsed =
1984 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
1985 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1986 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
1987 errs() <<
"error: no check strings found with prefix"
1988 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
1990 for (
StringRef MissingPrefix : PrefixesNotFound)
1991 errs() << LS <<
"\'" << MissingPrefix <<
":'";
1998 if (!DagNotMatches.empty()) {
1999 CheckStrings.emplace_back(
2002 std::move(DagNotMatches));
2016 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2017 bool PrintDiag =
true;
2042 assert(!HasError &&
"expected to report more diagnostics for error");
2047 std::string Message =
formatv(
"{0}: {1} string found in input",
2049 (ExpectedMatch ?
"expected" :
"excluded"))
2052 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2069 Diags->emplace<MatchCustomNoteDiag>(E.getRange(),
2070 E.getMessage().str(),
2085 bool HasError = ExpectedMatch;
2086 bool HasPatternError =
false;
2091 std::move(MatchError),
2093 HasError = HasPatternError =
true;
2103 bool PrintDiag =
true;
2105 if (!VerboseVerbose)
2128 assert(!HasError &&
"expected to report more diagnostics for error");
2134 if (!HasPatternError) {
2135 std::string Message =
formatv(
"{0}: {1} string not found in input",
2137 (ExpectedMatch ?
"expected" :
"excluded"))
2142 SM.PrintMessage(
Loc,
2146 "scanning from here");
2166 return printMatch(ExpectedMatch,
SM, Prefix,
Loc, Pat, MatchedCount, Buffer,
2167 std::move(MatchResult), Req, Diags);
2175 const char *&FirstNewLine) {
2176 unsigned NumNewLines = 0;
2191 if (NumNewLines == 1)
2192 FirstNewLine =
Range.begin();
2197 bool IsLabelScanMode,
size_t &MatchLen,
2201 std::vector<const DagNotPrefixInfo *> NotStrings;
2207 if (!IsLabelScanMode) {
2209 LastPos =
CheckDag(
SM, Buffer, NotStrings, Req, Diags);
2215 size_t LastMatchEnd = LastPos;
2216 size_t FirstMatchPos = 0;
2219 assert(
Pat.getCount() != 0 &&
"pattern count can not be zero");
2220 for (
int i = 1; i <=
Pat.getCount(); i++) {
2227 Pat, i, MatchBuffer,
2228 std::move(MatchResult), Req, Diags)) {
2233 size_t MatchPos = MatchResult.
TheMatch->Pos;
2235 FirstMatchPos = LastPos + MatchPos;
2238 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2241 MatchLen = LastMatchEnd - FirstMatchPos;
2245 if (!IsLabelScanMode) {
2246 size_t MatchPos = FirstMatchPos - LastPos;
2284 if (
CheckNot(
SM, SkippedRegion, NotStrings, Req, Diags))
2288 return FirstMatchPos;
2301 const char *FirstNewLine =
nullptr;
2304 if (NumNewLines == 0) {
2306 CheckName +
": is on the same line as previous match");
2308 "'next' match was here");
2310 "previous match ended here");
2314 if (NumNewLines != 1) {
2317 ": is not on the line after the previous match");
2319 "'next' match was here");
2321 "previous match ended here");
2323 "non-matching line after previous match is here");
2335 const char *FirstNewLine =
nullptr;
2338 if (NumNewLines != 0) {
2341 "-SAME: is not on the same line as the previous match");
2343 "'next' match was here");
2345 "previous match ended here");
2354 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2356 bool DirectiveFail =
false;
2357 for (
auto NotInfo : NotStrings) {
2359 "Expect CHECK-NOT!");
2362 false,
SM, NotInfo->DagNotPrefix,
2363 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2364 std::move(MatchResult), Req, Diags)) {
2366 DirectiveFail =
true;
2370 return DirectiveFail;
2375 std::vector<const DagNotPrefixInfo *> &NotStrings,
2382 size_t StartPos = 0;
2391 std::list<MatchRange> MatchRanges;
2396 PatItr != PatEnd; ++PatItr) {
2398 const StringRef DNPrefix = PatItr->DagNotPrefix;
2401 "Invalid CHECK-DAG or CHECK-NOT!");
2404 NotStrings.push_back(&*PatItr);
2411 size_t MatchLen = 0, MatchPos = StartPos;
2415 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2422 Pat.getLoc(),
Pat, 1, MatchBuffer,
2423 std::move(MatchResult), Req, Diags)) {
2429 MatchLen = MatchResult.
TheMatch->Len;
2432 MatchPos += MatchResult.
TheMatch->Pos;
2433 MatchRange M{MatchPos, MatchPos + MatchLen};
2438 if (MatchRanges.empty())
2439 MatchRanges.insert(MatchRanges.end(), M);
2441 auto Block = MatchRanges.begin();
2448 bool Overlap =
false;
2449 for (;
MI != ME; ++
MI) {
2450 if (M.Pos <
MI->End) {
2453 Overlap =
MI->Pos < M.End;
2459 MatchRanges.insert(
MI, M);
2471 SMRange OldRange(OldStart, OldEnd);
2473 "match discarded, overlaps earlier DAG match here",
2481 true,
SM, DNPrefix,
Pat.getLoc(),
Pat, 1, Buffer,
2486 if (std::next(PatItr) == PatEnd ||
2488 if (!NotStrings.empty()) {
2493 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2494 if (
CheckNot(
SM, SkippedRegion, NotStrings, Req, Diags))
2501 StartPos = MatchRanges.rbegin()->End;
2503 MatchRanges.clear();
2512 for (
StringRef Prefix : SuppliedPrefixes) {
2513 if (Prefix.empty()) {
2514 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2518 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2519 if (!Validator.
match(Prefix)) {
2520 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2521 <<
"letter and contain only alphanumeric characters, hyphens, and "
2522 <<
"underscores: '" << Prefix <<
"'\n";
2525 if (!UniquePrefixes.
insert(Prefix).second) {
2526 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2527 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2537 if (Req.CheckPrefixes.empty())
2539 if (Req.CommentPrefixes.empty())
2552 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2553 "Overriding defined variable with command-line variable definitions");
2555 if (CmdlineDefines.
empty())
2563 std::string CmdlineDefsDiag;
2565 for (
StringRef CmdlineDef : CmdlineDefines) {
2566 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2567 size_t EqIdx = CmdlineDef.find(
'=');
2569 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2573 if (CmdlineDef[0] ==
'#') {
2577 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2578 std::string SubstitutionStr = std::string(CmdlineDef);
2579 SubstitutionStr[EqIdx] =
':';
2581 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2582 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2584 CmdlineDefsDiag += DefPrefix;
2586 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2587 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2594 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2596 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2597 SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer),
SMLoc());
2599 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2600 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2601 CmdlineDefIndices.second);
2602 if (CmdlineDef.
empty()) {
2606 "missing equal sign in global definition"));
2611 if (CmdlineDef[0] ==
'#') {
2615 std::optional<NumericVariable *> DefinedNumericVariable;
2618 DefinedNumericVariable,
false,
2619 std::nullopt,
this,
SM);
2620 if (!ExpressionResult) {
2624 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2635 assert(DefinedNumericVariable &&
"No variable defined");
2636 (*DefinedNumericVariable)->setValue(*
Value);
2639 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2640 *DefinedNumericVariable;
2643 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2644 StringRef CmdlineName = CmdlineNameVal.first;
2645 StringRef OrigCmdlineName = CmdlineName;
2648 if (!ParseVarResult) {
2655 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2658 SM, OrigCmdlineName,
2659 "invalid name in string variable definition '" +
2660 OrigCmdlineName +
"'"));
2667 if (GlobalNumericVariableTable.contains(Name)) {
2670 "numeric variable with name '" +
2671 Name +
"' already exists"));
2674 GlobalVariableTable.insert(CmdlineNameVal);
2681 DefinedVariableTable[Name] =
true;
2691 if (Var.first()[0] !=
'$')
2692 LocalPatternVars.
push_back(Var.first());
2700 for (
const auto &Var : GlobalNumericVariableTable)
2701 if (Var.first()[0] !=
'$') {
2702 Var.getValue()->clearValue();
2703 LocalNumericVars.
push_back(Var.first());
2706 for (
const auto &Var : LocalPatternVars)
2707 GlobalVariableTable.erase(Var);
2708 for (
const auto &Var : LocalNumericVars)
2709 GlobalNumericVariableTable.erase(Var);
2714 bool ChecksFailed =
false;
2716 unsigned i = 0, j = 0, e = CheckStrings.size();
2720 CheckRegion = Buffer;
2729 size_t MatchLabelLen = 0;
2730 size_t MatchLabelPos =
2731 CheckLabelStr.
Check(
SM, Buffer,
true, MatchLabelLen, Req, Diags);
2736 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2737 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2744 if (i != 0 && Req.EnableVarScope)
2745 PatternContext->clearLocalVars();
2747 for (; i != j; ++i) {
2752 size_t MatchLen = 0;
2754 CheckStr.
Check(
SM, CheckRegion,
false, MatchLen, Req, Diags);
2757 ChecksFailed =
true;
2762 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2770 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 Error printMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error or (2) ErrorReported if an error was reported,...
static size_t SkipWord(StringRef Str, size_t Loc)
static SMRange buildMatchRange(StringRef Buffer, size_t Pos, size_t Len)
static SMRange buildSearchRange(StringRef Buffer)
static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported.
static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Error MatchError, bool VerboseVerbose, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported,...
static char popFront(StringRef &S)
constexpr StringLiteral SpaceChars
static std::pair< Check::FileCheckType, StringRef > FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix, bool &Misspelled)
static const char * DefaultCheckPrefixes[]
static const char * DefaultCommentPrefixes[]
static unsigned CountNumNewlinesBetween(StringRef Range, const char *&FirstNewLine)
Counts the number of newlines in the specified range.
static APInt toSigned(APInt AbsVal, bool Negative)
static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, ArrayRef< StringRef > SuppliedPrefixes)
static void addDefaultPrefixes(FileCheckRequest &Req)
static unsigned nextAPIntBitWidth(unsigned BitWidth)
static constexpr int BackrefLimit
static bool IsPartOfWord(char c)
static constexpr unsigned SM(unsigned Version)
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
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
A FileCheckDiag series emitted by the FileCheck library.
void emplace(ArgTys &&...Args)
Emplace a new FileCheckDiag of type DiagTy.
void adjustPrevMatchFoundDiag(MatchFoundDiag::StatusTy Status)
Adjust the previous MatchResultDiag, which must be a MatchFoundDiag, from successful status to unsucc...
virtual ~FileCheckDiag()=0
Destructor is purely virtual to ensure this remains an abstract class.
Class holding the Pattern global state, shared by all patterns: tables holding values of variables an...
LLVM_ABI_FOR_TEST Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
LLVM_ABI_FOR_TEST void createLineVariable()
Create @LINE pseudo variable.
LLVM_ABI_FOR_TEST Expected< StringRef > getPatternVarValue(StringRef VarName)
LLVM_ABI_FOR_TEST void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
LLVM_ABI bool readCheckFile(SourceMgr &SM, StringRef Buffer, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
LLVM_ABI StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
LLVM_ABI FileCheck(FileCheckRequest Req)
LLVM_ABI bool checkInput(SourceMgr &SM, StringRef Buffer, FileCheckDiagList *Diags=nullptr)
Checks the input to FileCheck provided in the Buffer against the expected strings read from the check...
LLVM_ABI bool ValidateCheckPrefixes()
A helper class to return the specified delimiter string after the first invocation of operator String...
MatchNoteDiag with a custom note not described by any other class derived from MatchNoteDiag.
MatchResultDiag for a pattern that matched the input.
@ Success
Indicates a good match for an expected pattern.
@ Excluded
Indicates a match for an excluded pattern (error).
@ Discarded
Indicates a discarded match for an expected pattern (not an error).
@ WrongLine
Indicates a match for an expected pattern, but the match is on the wrong line (error).
MatchNoteDiag for a fuzzy match that serves as a suggestion for the next intended match for an expect...
MatchResultDiag for a pattern that did not match the input.
@ Expected
Indicates no match for an expected pattern (error).
@ Success
Indicates no match for an excluded pattern.
@ InvalidPattern
Indicates no match due to an expected or excluded pattern that has proven to be invalid at match time...
virtual ~MatchNoteDiag()=0
Destructor is purely virtual to ensure this remains an abstract class.
virtual ~MatchResultDiag()=0
Destructor is purely virtual to ensure this remains an abstract class.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
const char * getBufferEnd() const
const char * getBufferStart() const
static LLVM_ABI_FOR_TEST char ID
Expected< std::string > getResultForDiagnostics() const override
Expected< std::string > getResultRegex() const override
Expected< APInt > eval() const override
Class representing a numeric variable and its associated current value.
void setValue(APInt NewValue, std::optional< StringRef > NewStrValue=std::nullopt)
Sets value of this numeric variable to NewValue, and sets the input buffer string from which it was p...
ExpressionFormat getImplicitFormat() const
std::optional< size_t > getDefLineNumber() const
Class to represent an overflow error that might result when manipulating a value.
static LLVM_ABI_FOR_TEST char ID
This class represents success/failure for parsing-like operations that find it important to chain tog...
static LLVM_ABI_FOR_TEST Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< Expression > > parseNumericSubstitutionBlock(StringRef Expr, std::optional< NumericVariable * > &DefinedNumericVariable, bool IsLegacyLineExpr, std::optional< size_t > LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM)
Parses Expr for a numeric substitution block at line LineNumber, or before input is parsed if LineNum...
LLVM_ABI_FOR_TEST void printVariableDefs(const SourceMgr &SM, FileCheckDiagList *Diags) const
static LLVM_ABI_FOR_TEST bool isValidVarNameStart(char C)
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, FileCheckDiagList *Diags) const
void printSubstitutions(const SourceMgr &SM, StringRef Buffer, SMRange MatchRange, FileCheckDiagList *Diags) const
Prints the value of successful substitutions.
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.
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.
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
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
Get the string size.
char front() const
Get the first character in the string.
constexpr const char * data() const
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)
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 CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, FileCheckDiagList *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is a single line in the given Buffer.
Pattern Pat
The pattern to match.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, FileCheckDiagList *Diags) const
Matches "dag strings" and their mixed "not strings".
bool CheckSame(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is no newline in the given Buffer.
std::vector< DagNotPrefixInfo > DagNotStrings
Hold the DAG/NOT strings occurring in the input file.
SMLoc Loc
The location in the match file that the check string was specified.
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, size_t &MatchLen, FileCheckRequest &Req, FileCheckDiagList *Diags) const
Matches check string and its "not strings" and/or "dag strings".
StringRef Prefix
Which prefix name this check matched.
std::optional< Match > TheMatch
Parsing information about a variable.