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;
1265 if (!Substitutions.empty()) {
1273 if (!MatchedValue) {
1280 OS << *MatchedValue;
1297 if (VariableDefs.empty() && NumericVariableDefs.empty())
1301 OS <<
"pattern attempts to capture variables: ";
1303 for (
const auto &Def : VariableDefs)
1304 OS << LS <<
'"' << Def.first <<
'"';
1305 for (
const auto &Def : NumericVariableDefs)
1306 OS << LS <<
'"' << Def.getKey() <<
'"';
1316 if (VariableDefs.empty() && NumericVariableDefs.empty())
1324 for (
const auto &VariableDef : VariableDefs) {
1326 VC.Name = VariableDef.first;
1330 VC.Range =
SMRange(Start, End);
1333 for (
const auto &VariableDef : NumericVariableDefs) {
1335 VC.Name = VariableDef.getKey();
1336 std::optional<StringRef> StrValue =
1337 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1342 VC.Range =
SMRange(Start, End);
1347 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1350 assert(
A.Range.Start !=
B.Range.Start &&
1351 "unexpected overlapping variable captures");
1352 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1355 for (
const VarCapture &VC : VarCaptures) {
1358 OS <<
"captured var \"" << VC.Name <<
"\"";
1382 size_t NumLinesForward = 0;
1384 double BestQuality = 0;
1387 if (
size_t(4096) *
size_t(2048) <
1388 std::min(
size_t(4096), Buffer.
size()) *
1389 std::max(FixedStr.size(), RegExStr.size()))
1393 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1394 if (Buffer[i] ==
'\n')
1399 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1404 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1405 double Quality = Distance + (NumLinesForward / 100.);
1409 BestQuality = Quality;
1421 "possible intended match here");
1430 auto VarIter = GlobalVariableTable.find(VarName);
1431 if (VarIter == GlobalVariableTable.end())
1434 return VarIter->second;
1437template <
class... Types>
1439 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1440 return NumericVariables.back().get();
1444FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1446 Substitutions.push_back(
1447 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1448 return Substitutions.back().get();
1451Substitution *FileCheckPatternContext::makeNumericSubstitution(
1454 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1455 this, ExpressionStr, std::move(Expression), InsertIdx));
1456 return Substitutions.back().get();
1463 size_t BracketDepth = 0;
1465 while (!Str.empty()) {
1466 if (Str.starts_with(
"]]") && BracketDepth == 0)
1468 if (Str[0] ==
'\\') {
1470 Str = Str.substr(2);
1480 if (BracketDepth == 0) {
1483 "missing closing \"]\" for regex variable");
1489 Str = Str.substr(1);
1502 Ptr != End; ++Ptr) {
1504 if (Ptr <= End - 2 && Ptr[0] ==
'\r' && Ptr[1] ==
'\n') {
1510 if (Req.NoCanonicalizeWhiteSpace || (*Ptr !=
' ' && *Ptr !=
'\t')) {
1517 while (Ptr + 1 != End && (Ptr[1] ==
' ' || Ptr[1] ==
'\t'))
1527 return (
isAlnum(c) || c ==
'-' || c ==
'_');
1531 assert(Count > 0 &&
"zero and negative counts are not supported");
1533 "count supported only for plain CHECK directives");
1539 if (Modifiers.none())
1552 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1560 return "misspelled";
1563 return WithModifiers(
"-COUNT");
1564 return WithModifiers(
"");
1566 return WithModifiers(
"-NEXT");
1568 return WithModifiers(
"-SAME");
1570 return WithModifiers(
"-NOT");
1572 return WithModifiers(
"-DAG");
1574 return WithModifiers(
"-LABEL");
1576 return WithModifiers(
"-EMPTY");
1578 return std::string(Prefix);
1580 return "implicit EOF";
1589static std::pair<Check::FileCheckType, StringRef>
1592 if (Buffer.
size() <= Prefix.size())
1605 -> std::pair<Check::FileCheckType, StringRef> {
1614 Rest = Rest.
ltrim();
1616 Ret.setLiteralMatch();
1620 Rest = Rest.
ltrim();
1630 if (Rest.
front() ==
'{')
1645 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1647 return ConsumeModifiers(
1679static std::pair<Check::FileCheckType, StringRef>
1681 bool Misspelled =
false;
1716 Prefixes.push_back({Prefix, Input.find(Prefix)});
1718 Prefixes.push_back({Prefix, Input.find(Prefix)});
1722 [](
auto A,
auto B) { return A.first.size() > B.first.size(); });
1730 "Buffer must be suffix of Input");
1732 size_t From = Buffer.
data() -
Input.data();
1734 for (
auto &[Prefix, Pos] :
Prefixes) {
1737 Pos =
Input.find(Prefix, From);
1770static std::pair<StringRef, StringRef>
1772 StringRef &Buffer,
unsigned &LineNumber,
1774 while (!Buffer.
empty()) {
1776 StringRef Prefix = Matcher.match(Buffer);
1782 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1783 "Prefix doesn't start inside of buffer!");
1784 size_t Loc = Prefix.data() - Buffer.
data();
1787 LineNumber += Skipped.count(
'\n');
1794 if (Skipped.empty() || !
IsPartOfWord(Skipped.back())) {
1797 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1801 return {Prefix, AfterSuffix};
1815 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1817 LineVariable = makeNumericVariable(
1819 GlobalNumericVariableTable[LineName] = LineVariable;
1829 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1830 if (ImpPatBufferIDRange)
1831 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1834 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1840 PatternContext->createLineVariable();
1842 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1843 for (
StringRef PatternString : Req.ImplicitCheckNot) {
1846 std::string Prefix =
"-implicit-check-not='";
1847 std::string Suffix =
"'";
1849 (Prefix + PatternString + Suffix).str(),
"command line");
1852 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1854 if (ImpPatBufferIDRange) {
1855 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1856 ImpPatBufferIDRange->first = BufferID;
1857 ImpPatBufferIDRange->second = BufferID + 1;
1859 assert(BufferID == ImpPatBufferIDRange->second &&
1860 "expected consecutive source buffer IDs");
1861 ++ImpPatBufferIDRange->second;
1865 ImplicitNegativeChecks.emplace_back(
1868 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1869 PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
1872 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1873 ImplicitNegativeChecks;
1876 unsigned LineNumber = 1;
1879 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1880 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1881 Req.CheckPrefixes.end());
1882 const size_t DistinctPrefixes = PrefixesNotFound.size();
1889 std::tie(UsedPrefix, AfterSuffix) =
1891 if (UsedPrefix.
empty())
1894 PrefixesNotFound.erase(UsedPrefix);
1897 "Failed to move Buffer's start forward, or pointed prefix outside "
1900 [[maybe_unused]]
const char *BufferEnd = Buffer.
data() + Buffer.
size();
1902 AfterSuffix.
data() <= BufferEnd &&
1903 "Parsing after suffix doesn't start inside of buffer!");
1906 Buffer = AfterSuffix;
1909 const char *UsedPrefixStart = UsedPrefix.
data();
1914 AfterSuffix.
data() - UsedPrefix.
data());
1917 "misspelled directive '" + UsedDirective +
"'");
1924 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1931 "invalid count in -COUNT specification on prefix '" +
1938 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1949 Buffer = Buffer.
substr(EOL);
1956 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1957 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1964 "found '" + UsedPrefix +
"-LABEL:'"
1965 " with variable definition or use");
1972 CheckStrings.empty()) {
1978 "found '" + UsedPrefix +
"-" +
Type +
1979 "' without previous '" + UsedPrefix +
": line");
1985 DagNotMatches.emplace_back(
P, UsedPrefix);
1990 CheckStrings.emplace_back(std::move(
P), UsedPrefix, PatternLoc,
1991 std::move(DagNotMatches));
1992 DagNotMatches = ImplicitNegativeChecks;
1997 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1998 const bool SomePrefixesUnexpectedlyNotUsed =
1999 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
2000 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
2001 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
2002 errs() <<
"error: no check strings found with prefix"
2003 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
2005 for (
StringRef MissingPrefix : PrefixesNotFound)
2006 errs() << LS <<
"\'" << MissingPrefix <<
":'";
2013 if (!DagNotMatches.empty()) {
2014 CheckStrings.emplace_back(
2017 std::move(DagNotMatches));
2031 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2032 bool PrintDiag =
true;
2057 assert(!HasError &&
"expected to report more diagnostics for error");
2062 std::string Message =
formatv(
"{0}: {1} string found in input",
2064 (ExpectedMatch ?
"expected" :
"excluded"))
2067 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2084 Diags->emplace<MatchCustomNoteDiag>(E.getRange(),
2085 E.getMessage().str(),
2100 bool HasError = ExpectedMatch;
2101 bool HasPatternError =
false;
2106 std::move(MatchError),
2108 HasError = HasPatternError =
true;
2118 bool PrintDiag =
true;
2120 if (!VerboseVerbose)
2144 assert(!HasError &&
"expected to report more diagnostics for error");
2150 if (!HasPatternError) {
2151 std::string Message =
formatv(
"{0}: {1} string not found in input",
2153 (ExpectedMatch ?
"expected" :
"excluded"))
2162 "scanning from here");
2184 return printMatch(ExpectedMatch, SM, Prefix,
Loc, Pat, MatchedCount, Buffer,
2185 std::move(MatchResult), Req, Diags);
2186 return printNoMatch(ExpectedMatch, SM, Prefix,
Loc, Pat, MatchedCount, Buffer,
2193 const char *&FirstNewLine) {
2194 unsigned NumNewLines = 0;
2209 if (NumNewLines == 1)
2210 FirstNewLine =
Range.begin();
2215 bool IsLabelScanMode,
size_t &MatchLen,
2219 std::vector<const DagNotPrefixInfo *> NotStrings;
2225 if (!IsLabelScanMode) {
2227 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2233 size_t LastMatchEnd = LastPos;
2234 size_t FirstMatchPos = 0;
2237 assert(
Pat.getCount() != 0 &&
"pattern count can not be zero");
2238 for (
int i = 1; i <=
Pat.getCount(); i++) {
2245 Pat, i, MatchBuffer,
2246 std::move(MatchResult), Req, Diags)) {
2251 size_t MatchPos = MatchResult.
TheMatch->Pos;
2253 FirstMatchPos = LastPos + MatchPos;
2256 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2259 MatchLen = LastMatchEnd - FirstMatchPos;
2263 if (!IsLabelScanMode) {
2264 size_t MatchPos = FirstMatchPos - LastPos;
2302 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2306 return FirstMatchPos;
2319 const char *FirstNewLine =
nullptr;
2322 if (NumNewLines == 0) {
2324 CheckName +
": is on the same line as previous match");
2326 "'next' match was here");
2328 "previous match ended here");
2332 if (NumNewLines != 1) {
2335 ": is not on the line after the previous match");
2337 "'next' match was here");
2339 "previous match ended here");
2341 "non-matching line after previous match is here");
2353 const char *FirstNewLine =
nullptr;
2356 if (NumNewLines != 0) {
2359 "-SAME: is not on the same line as the previous match");
2361 "'next' match was here");
2363 "previous match ended here");
2372 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2374 bool DirectiveFail =
false;
2375 for (
auto NotInfo : NotStrings) {
2377 "Expect CHECK-NOT!");
2380 false, SM, NotInfo->DagNotPrefix,
2381 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2382 std::move(MatchResult), Req, Diags)) {
2384 DirectiveFail =
true;
2388 return DirectiveFail;
2393 std::vector<const DagNotPrefixInfo *> &NotStrings,
2400 size_t StartPos = 0;
2409 std::list<MatchRange> MatchRanges;
2414 PatItr != PatEnd; ++PatItr) {
2416 const StringRef DNPrefix = PatItr->DagNotPrefix;
2419 "Invalid CHECK-DAG or CHECK-NOT!");
2422 NotStrings.push_back(&*PatItr);
2429 size_t MatchLen = 0, MatchPos = StartPos;
2433 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2440 Pat.getLoc(),
Pat, 1, MatchBuffer,
2441 std::move(MatchResult), Req, Diags)) {
2447 MatchLen = MatchResult.
TheMatch->Len;
2450 MatchPos += MatchResult.
TheMatch->Pos;
2451 MatchRange M{MatchPos, MatchPos + MatchLen};
2456 if (MatchRanges.empty())
2457 MatchRanges.insert(MatchRanges.end(), M);
2459 auto Block = MatchRanges.begin();
2466 bool Overlap =
false;
2467 for (;
MI != ME; ++
MI) {
2468 if (M.Pos <
MI->End) {
2471 Overlap =
MI->Pos < M.End;
2477 MatchRanges.insert(
MI, M);
2489 SMRange OldRange(OldStart, OldEnd);
2491 "match discarded, overlaps earlier DAG match here",
2499 true, SM, DNPrefix,
Pat.getLoc(),
Pat, 1, Buffer,
2504 if (std::next(PatItr) == PatEnd ||
2506 if (!NotStrings.empty()) {
2511 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2512 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2519 StartPos = MatchRanges.rbegin()->End;
2521 MatchRanges.clear();
2530 for (
StringRef Prefix : SuppliedPrefixes) {
2531 if (Prefix.empty()) {
2532 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2536 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2537 if (!Validator.
match(Prefix)) {
2538 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2539 <<
"letter and contain only alphanumeric characters, hyphens, and "
2540 <<
"underscores: '" << Prefix <<
"'\n";
2543 if (!UniquePrefixes.
insert(Prefix).second) {
2544 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2545 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2555 if (Req.CheckPrefixes.empty())
2557 if (Req.CommentPrefixes.empty())
2570 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2571 "Overriding defined variable with command-line variable definitions");
2573 if (CmdlineDefines.
empty())
2581 std::string CmdlineDefsDiag;
2583 for (
StringRef CmdlineDef : CmdlineDefines) {
2584 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2585 size_t EqIdx = CmdlineDef.find(
'=');
2587 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2591 if (CmdlineDef[0] ==
'#') {
2595 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2596 std::string SubstitutionStr = std::string(CmdlineDef);
2597 SubstitutionStr[EqIdx] =
':';
2599 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2600 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2602 CmdlineDefsDiag += DefPrefix;
2604 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2605 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2612 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2614 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2617 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2618 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2619 CmdlineDefIndices.second);
2620 if (CmdlineDef.
empty()) {
2624 "missing equal sign in global definition"));
2629 if (CmdlineDef[0] ==
'#') {
2633 std::optional<NumericVariable *> DefinedNumericVariable;
2636 DefinedNumericVariable,
false,
2637 std::nullopt,
this, SM);
2638 if (!ExpressionResult) {
2642 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2653 assert(DefinedNumericVariable &&
"No variable defined");
2654 (*DefinedNumericVariable)->setValue(*
Value);
2657 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2658 *DefinedNumericVariable;
2661 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2662 StringRef CmdlineName = CmdlineNameVal.first;
2663 StringRef OrigCmdlineName = CmdlineName;
2666 if (!ParseVarResult) {
2673 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2676 SM, OrigCmdlineName,
2677 "invalid name in string variable definition '" +
2678 OrigCmdlineName +
"'"));
2685 if (GlobalNumericVariableTable.contains(Name)) {
2688 "numeric variable with name '" +
2689 Name +
"' already exists"));
2692 GlobalVariableTable.insert(CmdlineNameVal);
2699 DefinedVariableTable[Name] =
true;
2709 if (Var.first()[0] !=
'$')
2710 LocalPatternVars.
push_back(Var.first());
2718 for (
const auto &Var : GlobalNumericVariableTable)
2719 if (Var.first()[0] !=
'$') {
2720 Var.getValue()->clearValue();
2721 LocalNumericVars.
push_back(Var.first());
2724 for (
const auto &Var : LocalPatternVars)
2725 GlobalVariableTable.erase(Var);
2726 for (
const auto &Var : LocalNumericVars)
2727 GlobalNumericVariableTable.erase(Var);
2732 bool ChecksFailed =
false;
2734 unsigned i = 0, j = 0, e = CheckStrings.size();
2738 CheckRegion = Buffer;
2747 size_t MatchLabelLen = 0;
2748 size_t MatchLabelPos =
2749 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2754 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2755 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2762 if (i != 0 && Req.EnableVarScope)
2763 PatternContext->clearLocalVars();
2765 for (; i != j; ++i) {
2770 size_t MatchLen = 0;
2772 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2775 ChecksFailed =
true;
2780 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2788 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, PrefixMatcher &Matcher, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
static Error printMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error or (2) ErrorReported if an error was reported,...
static size_t SkipWord(StringRef Str, size_t Loc)
static SMRange buildMatchRange(StringRef Buffer, size_t Pos, size_t Len)
static SMRange buildSearchRange(StringRef Buffer)
static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported.
static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Error MatchError, bool VerboseVerbose, FileCheckDiagList *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported,...
static char popFront(StringRef &S)
constexpr StringLiteral SpaceChars
static std::pair< Check::FileCheckType, StringRef > FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix, bool &Misspelled)
static const char * DefaultCheckPrefixes[]
static const char * DefaultCommentPrefixes[]
static unsigned CountNumNewlinesBetween(StringRef Range, const char *&FirstNewLine)
Counts the number of newlines in the specified range.
static APInt toSigned(APInt AbsVal, bool Negative)
static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, ArrayRef< StringRef > SuppliedPrefixes)
static void addDefaultPrefixes(FileCheckRequest &Req)
static unsigned nextAPIntBitWidth(unsigned BitWidth)
static constexpr int BackrefLimit
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.
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...
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...
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.
void printVariableDefAttempts(const SourceMgr &SM, StringRef Buffer, FileCheckDiagList *Diags) const
Prints a list of all variables that this pattern attempts to capture.
@ Newline
Compile for newline-sensitive matching.
@ 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 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.
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.
@ 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)
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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.