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())
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'))
1531 return (
isAlnum(c) || c ==
'-' || c ==
'_');
1535 assert(Count > 0 &&
"zero and negative counts are not supported");
1537 "count supported only for plain CHECK directives");
1543 if (Modifiers.none())
1556 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1564 return "misspelled";
1567 return WithModifiers(
"-COUNT");
1568 return WithModifiers(
"");
1570 return WithModifiers(
"-NEXT");
1572 return WithModifiers(
"-SAME");
1574 return WithModifiers(
"-NOT");
1576 return WithModifiers(
"-DAG");
1578 return WithModifiers(
"-LABEL");
1580 return WithModifiers(
"-EMPTY");
1582 return std::string(Prefix);
1584 return "implicit EOF";
1593static std::pair<Check::FileCheckType, StringRef>
1596 if (Buffer.
size() <= Prefix.size())
1609 -> std::pair<Check::FileCheckType, StringRef> {
1618 Rest = Rest.
ltrim();
1620 Ret.setLiteralMatch();
1624 Rest = Rest.
ltrim();
1634 if (Rest.
front() ==
'{')
1649 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1651 return ConsumeModifiers(
1683static std::pair<Check::FileCheckType, StringRef>
1685 bool Misspelled =
false;
1720 Prefixes.push_back({Prefix, Input.find(Prefix)});
1722 Prefixes.push_back({Prefix, Input.find(Prefix)});
1726 [](
auto A,
auto B) { return A.first.size() > B.first.size(); });
1734 "Buffer must be suffix of Input");
1736 size_t From = Buffer.
data() -
Input.data();
1738 for (
auto &[Prefix, Pos] :
Prefixes) {
1741 Pos =
Input.find(Prefix, From);
1774static std::pair<StringRef, StringRef>
1776 StringRef &Buffer,
unsigned &LineNumber,
1778 while (!Buffer.
empty()) {
1780 StringRef Prefix = Matcher.match(Buffer);
1786 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1787 "Prefix doesn't start inside of buffer!");
1788 size_t Loc = Prefix.data() - Buffer.
data();
1791 LineNumber += Skipped.count(
'\n');
1798 if (Skipped.empty() || !
IsPartOfWord(Skipped.back())) {
1801 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1805 return {Prefix, AfterSuffix};
1819 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1821 LineVariable = makeNumericVariable(
1823 GlobalNumericVariableTable[LineName] = LineVariable;
1833 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1834 if (ImpPatBufferIDRange)
1835 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1838 PatternContext->defineCmdlineVariables(Req.GlobalDefines,
SM);
1844 PatternContext->createLineVariable();
1846 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1847 for (
StringRef PatternString : Req.ImplicitCheckNot) {
1850 std::string Prefix =
"-implicit-check-not='";
1851 std::string Suffix =
"'";
1853 (Prefix + PatternString + Suffix).str(),
"command line");
1856 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1857 unsigned BufferID =
SM.AddNewSourceBuffer(std::move(CmdLine),
SMLoc());
1858 if (ImpPatBufferIDRange) {
1859 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1860 ImpPatBufferIDRange->first = BufferID;
1861 ImpPatBufferIDRange->second = BufferID + 1;
1863 assert(BufferID == ImpPatBufferIDRange->second &&
1864 "expected consecutive source buffer IDs");
1865 ++ImpPatBufferIDRange->second;
1869 ImplicitNegativeChecks.emplace_back(
1872 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1873 PatternInBuffer,
"IMPLICIT-CHECK",
SM, Req);
1876 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1877 ImplicitNegativeChecks;
1880 unsigned LineNumber = 1;
1883 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1884 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1885 Req.CheckPrefixes.end());
1886 const size_t DistinctPrefixes = PrefixesNotFound.size();
1893 std::tie(UsedPrefix, AfterSuffix) =
1895 if (UsedPrefix.
empty())
1898 PrefixesNotFound.erase(UsedPrefix);
1901 "Failed to move Buffer's start forward, or pointed prefix outside "
1904 [[maybe_unused]]
const char *BufferEnd = Buffer.
data() + Buffer.
size();
1906 AfterSuffix.
data() <= BufferEnd &&
1907 "Parsing after suffix doesn't start inside of buffer!");
1910 Buffer = AfterSuffix;
1913 const char *UsedPrefixStart = UsedPrefix.
data();
1918 AfterSuffix.
data() - UsedPrefix.
data());
1921 "misspelled directive '" + UsedDirective +
"'");
1928 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1935 "invalid count in -COUNT specification on prefix '" +
1942 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1953 Buffer = Buffer.
substr(EOL);
1960 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1961 if (
P.parsePattern(PatternBuffer, UsedPrefix,
SM, Req))
1968 "found '" + UsedPrefix +
"-LABEL:'"
1969 " with variable definition or use");
1976 CheckStrings.empty()) {
1982 "found '" + UsedPrefix +
"-" +
Type +
1983 "' without previous '" + UsedPrefix +
": line");
1989 DagNotMatches.emplace_back(
P, UsedPrefix);
1994 CheckStrings.emplace_back(std::move(
P), UsedPrefix, PatternLoc,
1995 std::move(DagNotMatches));
1996 DagNotMatches = ImplicitNegativeChecks;
2001 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
2002 const bool SomePrefixesUnexpectedlyNotUsed =
2003 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
2004 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
2005 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
2006 errs() <<
"error: no check strings found with prefix"
2007 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
2009 for (
StringRef MissingPrefix : PrefixesNotFound)
2010 errs() << LS <<
"\'" << MissingPrefix <<
":'";
2017 if (!DagNotMatches.empty()) {
2018 CheckStrings.emplace_back(
2021 std::move(DagNotMatches));
2035 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2036 bool PrintDiag =
true;
2061 assert(!HasError &&
"expected to report more diagnostics for error");
2066 std::string Message =
formatv(
"{0}: {1} string found in input",
2068 (ExpectedMatch ?
"expected" :
"excluded"))
2071 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2088 Diags->emplace<MatchCustomNoteDiag>(E.getRange(),
2089 E.getMessage().str(),
2104 bool HasError = ExpectedMatch;
2105 bool HasPatternError =
false;
2110 std::move(MatchError),
2112 HasError = HasPatternError =
true;
2122 bool PrintDiag =
true;
2124 if (!VerboseVerbose)
2148 assert(!HasError &&
"expected to report more diagnostics for error");
2154 if (!HasPatternError) {
2155 std::string Message =
formatv(
"{0}: {1} string not found in input",
2157 (ExpectedMatch ?
"expected" :
"excluded"))
2162 SM.PrintMessage(
Loc,
2166 "scanning from here");
2188 return printMatch(ExpectedMatch,
SM, Prefix,
Loc, Pat, MatchedCount, Buffer,
2189 std::move(MatchResult), Req, Diags);
2197 const char *&FirstNewLine) {
2198 unsigned NumNewLines = 0;
2213 if (NumNewLines == 1)
2214 FirstNewLine =
Range.begin();
2219 bool IsLabelScanMode,
size_t &MatchLen,
2223 std::vector<const DagNotPrefixInfo *> NotStrings;
2229 if (!IsLabelScanMode) {
2231 LastPos =
CheckDag(
SM, Buffer, NotStrings, Req, Diags);
2237 size_t LastMatchEnd = LastPos;
2238 size_t FirstMatchPos = 0;
2241 assert(
Pat.getCount() != 0 &&
"pattern count can not be zero");
2242 for (
int i = 1; i <=
Pat.getCount(); i++) {
2249 Pat, i, MatchBuffer,
2250 std::move(MatchResult), Req, Diags)) {
2255 size_t MatchPos = MatchResult.
TheMatch->Pos;
2257 FirstMatchPos = LastPos + MatchPos;
2260 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2263 MatchLen = LastMatchEnd - FirstMatchPos;
2267 if (!IsLabelScanMode) {
2268 size_t MatchPos = FirstMatchPos - LastPos;
2306 if (
CheckNot(
SM, SkippedRegion, NotStrings, Req, Diags))
2310 return FirstMatchPos;
2323 const char *FirstNewLine =
nullptr;
2326 if (NumNewLines == 0) {
2328 CheckName +
": is on the same line as previous match");
2330 "'next' match was here");
2332 "previous match ended here");
2336 if (NumNewLines != 1) {
2339 ": is not on the line after the previous match");
2341 "'next' match was here");
2343 "previous match ended here");
2345 "non-matching line after previous match is here");
2357 const char *FirstNewLine =
nullptr;
2360 if (NumNewLines != 0) {
2363 "-SAME: is not on the same line as the previous match");
2365 "'next' match was here");
2367 "previous match ended here");
2376 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2378 bool DirectiveFail =
false;
2379 for (
auto NotInfo : NotStrings) {
2381 "Expect CHECK-NOT!");
2384 false,
SM, NotInfo->DagNotPrefix,
2385 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2386 std::move(MatchResult), Req, Diags)) {
2388 DirectiveFail =
true;
2392 return DirectiveFail;
2397 std::vector<const DagNotPrefixInfo *> &NotStrings,
2404 size_t StartPos = 0;
2413 std::list<MatchRange> MatchRanges;
2418 PatItr != PatEnd; ++PatItr) {
2420 const StringRef DNPrefix = PatItr->DagNotPrefix;
2423 "Invalid CHECK-DAG or CHECK-NOT!");
2426 NotStrings.push_back(&*PatItr);
2433 size_t MatchLen = 0, MatchPos = StartPos;
2437 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2444 Pat.getLoc(),
Pat, 1, MatchBuffer,
2445 std::move(MatchResult), Req, Diags)) {
2451 MatchLen = MatchResult.
TheMatch->Len;
2454 MatchPos += MatchResult.
TheMatch->Pos;
2455 MatchRange M{MatchPos, MatchPos + MatchLen};
2460 if (MatchRanges.empty())
2461 MatchRanges.insert(MatchRanges.end(), M);
2463 auto Block = MatchRanges.begin();
2470 bool Overlap =
false;
2471 for (;
MI != ME; ++
MI) {
2472 if (M.Pos <
MI->End) {
2475 Overlap =
MI->Pos < M.End;
2481 MatchRanges.insert(
MI, M);
2493 SMRange OldRange(OldStart, OldEnd);
2495 "match discarded, overlaps earlier DAG match here",
2503 true,
SM, DNPrefix,
Pat.getLoc(),
Pat, 1, Buffer,
2508 if (std::next(PatItr) == PatEnd ||
2510 if (!NotStrings.empty()) {
2515 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2516 if (
CheckNot(
SM, SkippedRegion, NotStrings, Req, Diags))
2523 StartPos = MatchRanges.rbegin()->End;
2525 MatchRanges.clear();
2534 for (
StringRef Prefix : SuppliedPrefixes) {
2535 if (Prefix.empty()) {
2536 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2540 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2541 if (!Validator.
match(Prefix)) {
2542 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2543 <<
"letter and contain only alphanumeric characters, hyphens, and "
2544 <<
"underscores: '" << Prefix <<
"'\n";
2547 if (!UniquePrefixes.
insert(Prefix).second) {
2548 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2549 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2559 if (Req.CheckPrefixes.empty())
2561 if (Req.CommentPrefixes.empty())
2574 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2575 "Overriding defined variable with command-line variable definitions");
2577 if (CmdlineDefines.
empty())
2585 std::string CmdlineDefsDiag;
2587 for (
StringRef CmdlineDef : CmdlineDefines) {
2588 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2589 size_t EqIdx = CmdlineDef.find(
'=');
2591 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2595 if (CmdlineDef[0] ==
'#') {
2599 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2600 std::string SubstitutionStr = std::string(CmdlineDef);
2601 SubstitutionStr[EqIdx] =
':';
2603 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2604 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2606 CmdlineDefsDiag += DefPrefix;
2608 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2609 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2616 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2618 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2619 SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer),
SMLoc());
2621 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2622 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2623 CmdlineDefIndices.second);
2624 if (CmdlineDef.
empty()) {
2628 "missing equal sign in global definition"));
2633 if (CmdlineDef[0] ==
'#') {
2637 std::optional<NumericVariable *> DefinedNumericVariable;
2640 DefinedNumericVariable,
false,
2641 std::nullopt,
this,
SM);
2642 if (!ExpressionResult) {
2646 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2657 assert(DefinedNumericVariable &&
"No variable defined");
2658 (*DefinedNumericVariable)->setValue(*
Value);
2661 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2662 *DefinedNumericVariable;
2665 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2666 StringRef CmdlineName = CmdlineNameVal.first;
2667 StringRef OrigCmdlineName = CmdlineName;
2670 if (!ParseVarResult) {
2677 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2680 SM, OrigCmdlineName,
2681 "invalid name in string variable definition '" +
2682 OrigCmdlineName +
"'"));
2689 if (GlobalNumericVariableTable.contains(Name)) {
2692 "numeric variable with name '" +
2693 Name +
"' already exists"));
2696 GlobalVariableTable.insert(CmdlineNameVal);
2703 DefinedVariableTable[Name] =
true;
2713 if (Var.first()[0] !=
'$')
2714 LocalPatternVars.
push_back(Var.first());
2722 for (
const auto &Var : GlobalNumericVariableTable)
2723 if (Var.first()[0] !=
'$') {
2724 Var.getValue()->clearValue();
2725 LocalNumericVars.
push_back(Var.first());
2728 for (
const auto &Var : LocalPatternVars)
2729 GlobalVariableTable.erase(Var);
2730 for (
const auto &Var : LocalNumericVars)
2731 GlobalNumericVariableTable.erase(Var);
2736 bool ChecksFailed =
false;
2738 unsigned i = 0, j = 0, e = CheckStrings.size();
2742 CheckRegion = Buffer;
2751 size_t MatchLabelLen = 0;
2752 size_t MatchLabelPos =
2753 CheckLabelStr.
Check(
SM, Buffer,
true, MatchLabelLen, Req, Diags);
2758 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2759 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2766 if (i != 0 && Req.EnableVarScope)
2767 PatternContext->clearLocalVars();
2769 for (; i != j; ++i) {
2774 size_t MatchLen = 0;
2776 CheckStr.
Check(
SM, CheckRegion,
false, MatchLen, Req, Diags);
2779 ChecksFailed =
true;
2784 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2792 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.
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.
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)
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.