50 auto CreatePrecisionRegex = [&](
StringRef S) {
51 return (
Twine(AlternateFormPrefix) + S +
Twine(
'{') +
Twine(Precision) +
59 return CreatePrecisionRegex(
"([1-9][0-9]*)?[0-9]");
60 return std::string(
"[0-9]+");
63 return CreatePrecisionRegex(
"-?([1-9][0-9]*)?[0-9]");
64 return std::string(
"-?[0-9]+");
67 return CreatePrecisionRegex(
"([1-9A-F][0-9A-F]*)?[0-9A-F]");
68 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9A-F]+")).str();
71 return CreatePrecisionRegex(
"([1-9a-f][0-9a-f]*)?[0-9a-f]");
72 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9a-f]+")).str();
75 "trying to match value with invalid format");
85 bool UpperCase =
false;
103 "trying to match value with invalid format");
105 IntValue.
abs().
toString(AbsoluteValueStr, Radix,
false,
111 if (Precision > AbsoluteValueStr.
size()) {
112 unsigned LeadingZeros = Precision - AbsoluteValueStr.
size();
113 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
114 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
118 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
130 APInt Result = AbsVal;
139 bool Negative = StrVal.consume_front(
"-");
141 bool MissingFormPrefix =
142 !ValueIsSigned && AlternateForm && !StrVal.consume_front(
"0x");
143 (void)MissingFormPrefix;
144 assert(!MissingFormPrefix &&
"missing alternate form prefix");
146 [[maybe_unused]]
bool ParseFailure =
147 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
151 assert(!ParseFailure &&
"unable to represent numeric value");
152 return toSigned(ResultValue, Negative);
156 const APInt &RightOperand,
bool &Overflow) {
157 return LeftOperand.
sadd_ov(RightOperand, Overflow);
161 const APInt &RightOperand,
bool &Overflow) {
162 return LeftOperand.
ssub_ov(RightOperand, Overflow);
166 const APInt &RightOperand,
bool &Overflow) {
167 return LeftOperand.
smul_ov(RightOperand, Overflow);
171 const APInt &RightOperand,
bool &Overflow) {
173 if (RightOperand.
isZero())
176 return LeftOperand.
sdiv_ov(RightOperand, Overflow);
180 const APInt &RightOperand,
bool &Overflow) {
182 return LeftOperand.
slt(RightOperand) ? RightOperand : LeftOperand;
186 const APInt &RightOperand,
bool &Overflow) {
188 if (
cantFail(
exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
195 std::optional<APInt>
Value = Variable->getValue();
208 if (!MaybeLeftOp || !MaybeRightOp) {
214 return std::move(Err);
217 APInt LeftOp = *MaybeLeftOp;
218 APInt RightOp = *MaybeRightOp;
223 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
224 LeftOp = LeftOp.
sext(NewBitWidth);
225 RightOp = RightOp.
sext(NewBitWidth);
235 LeftOp = LeftOp.
sext(NewBitWidth);
236 RightOp = RightOp.
sext(NewBitWidth);
244 if (!LeftFormat || !RightFormat) {
250 return std::move(Err);
255 *LeftFormat != *RightFormat)
258 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
259 "' (" + LeftFormat->toString() +
") and '" +
260 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
261 "), need an explicit format specifier");
268 assert(ExpressionPointer->getAST() !=
nullptr &&
269 "Substituting empty expression");
274 return Format.getMatchingString(*EvaluatedValue);
285 return "\"" + std::move(*
Literal) +
"\"";
302 Result.reserve(VarVal->size() + 2);
313 const bool NeedsEscaping =
321 OS <<
" (escaped value)";
334 bool IsPseudo = Str[0] ==
'@';
337 if (Str[0] ==
'$' || IsPseudo)
343 (IsPseudo ?
"pseudo " :
"global ") +
349 for (
size_t E = Str.size();
I != E; ++
I)
380 Expected<VariableProperties> ParseVarResult =
parseVariable(Expr, SM);
383 StringRef
Name = ParseVarResult->Name;
385 if (ParseVarResult->IsPseudo)
387 SM, Name,
"definition of pseudo numeric variable unsupported");
391 if (Context->DefinedVariableTable.contains(Name))
393 SM, Name,
"string variable with name '" + Name +
"' already exists");
398 SM, Expr,
"unexpected characters after numeric variable name");
400 NumericVariable *DefinedNumericVariable;
401 auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
402 if (VarTableIter != Context->GlobalNumericVariableTable.end()) {
403 DefinedNumericVariable = VarTableIter->second;
406 SM, Expr,
"format different from previous variable definition");
408 DefinedNumericVariable =
409 Context->makeNumericVariable(Name, ImplicitFormat, LineNumber);
411 return DefinedNumericVariable;
415 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
417 if (IsPseudo && Name !=
"@LINE")
419 SM, Name,
"invalid pseudo numeric variable '" + Name +
"'");
430 Context->GlobalNumericVariableTable.try_emplace(Name);
432 VarTableIter->second = Context->makeNumericVariable(
434 NumericVariable *NumericVariable = VarTableIter->second;
437 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
440 "numeric variable '" + Name +
441 "' defined earlier in the same CHECK directive");
443 return std::make_unique<NumericVariableUse>(Name, NumericVariable);
447 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
451 if (AO != AllowedOperand::Any)
453 SM, Expr,
"parenthesized expression not permitted here");
454 return parseParenExpr(Expr, LineNumber, Context, SM);
457 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
459 Expected<Pattern::VariableProperties> ParseVarResult =
461 if (ParseVarResult) {
464 if (AO != AllowedOperand::Any)
466 "unexpected function call");
468 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
472 return parseNumericVariableUse(ParseVarResult->Name,
473 ParseVarResult->IsPseudo, LineNumber,
477 if (AO == AllowedOperand::LineVar)
485 StringRef SaveExpr = Expr;
487 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
490 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
496 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
501Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
513 Expected<std::unique_ptr<ExpressionAST>> SubExprResult = parseNumericOperand(
514 Expr, AllowedOperand::Any,
false, LineNumber,
518 StringRef OrigExpr = Expr;
519 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
520 LineNumber, Context, SM);
524 return SubExprResult;
528 "missing ')' at end of nested expression");
530 return SubExprResult;
535 std::unique_ptr<ExpressionAST> LeftOp,
536 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
539 if (RemainingExpr.
empty())
540 return std::move(LeftOp);
556 SM, OpLoc, Twine(
"unsupported operation '") + Twine(Operator) +
"'");
561 if (RemainingExpr.
empty())
563 "missing operand in expression");
566 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
567 Expected<std::unique_ptr<ExpressionAST>> RightOpResult =
568 parseNumericOperand(RemainingExpr, AO,
false,
569 LineNumber, Context, SM);
571 return RightOpResult;
574 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
575 std::move(*RightOpResult));
580 std::optional<size_t> LineNumber,
585 auto OptFunc = StringSwitch<binop_eval_t>(FuncName)
596 SM, FuncName, Twine(
"call to undefined function '") + FuncName +
"'");
608 StringRef OuterBinOpExpr = Expr;
609 Expected<std::unique_ptr<ExpressionAST>> Arg = parseNumericOperand(
610 Expr, AllowedOperand::Any,
false, LineNumber,
612 while (Arg && !Expr.
empty()) {
619 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg),
false, LineNumber,
626 Args.push_back(std::move(*Arg));
640 "missing ')' at end of call expression");
642 const unsigned NumArgs =
Args.size();
644 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
649 Twine(
"function '") + FuncName +
650 Twine(
"' takes 2 arguments but ") +
651 Twine(NumArgs) +
" given");
655 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
656 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
658 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
660 DefinedNumericVariable = std::nullopt;
662 unsigned Precision = 0;
665 size_t FormatSpecEnd = Expr.
find(
',');
666 size_t FunctionStart = Expr.
find(
'(');
667 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
674 "invalid matching format specification in expression");
684 "invalid precision in format specifier");
687 if (!FormatExpr.
empty()) {
702 Precision, AlternateForm);
706 Precision, AlternateForm);
710 "invalid format specifier in expression");
717 SM, AlternateFormFlagLoc,
718 "alternate form only supported for hex values");
721 if (!FormatExpr.
empty())
724 "invalid matching format specification in expression");
728 size_t DefEnd = Expr.
find(
':');
730 DefExpr = Expr.
substr(0, DefEnd);
731 Expr = Expr.
substr(DefEnd + 1);
741 if (HasParsedValidConstraint)
743 SM, Expr,
"empty numeric expression should not have a constraint");
750 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
752 Expr, AO, !HasParsedValidConstraint, LineNumber, Context, SM);
755 IsLegacyLineExpr, LineNumber, Context, SM);
760 "unexpected characters at end of expression '" + Expr +
"'");
774 else if (ExpressionASTPointer) {
776 ExpressionASTPointer->getImplicitFormat(SM);
784 std::unique_ptr<Expression> ExpressionPointer =
785 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
791 DefExpr, Context, LineNumber, ExpressionPointer->getFormat(), SM);
798 return std::move(ExpressionPointer);
810 PatternStr = PatternStr.
rtrim(
" \t");
815 "found empty check string with prefix '" + Prefix +
":'");
822 "found non-empty check string for empty check with prefix '" + Prefix +
833 if (CheckTy.isLiteralMatch()) {
834 FixedStr = PatternStr;
839 if (!MatchFullLinesHere &&
840 (PatternStr.
size() < 2 ||
842 FixedStr = PatternStr;
846 if (MatchFullLinesHere) {
854 unsigned CurParen = 1;
858 while (!PatternStr.
empty()) {
862 size_t End = PatternStr.
find(
"}}");
866 "found start of regex string with no end '}}'");
874 bool HasAlternation = PatternStr.
contains(
'|');
875 if (HasAlternation) {
880 if (AddRegExToRegEx(PatternStr.
substr(2, End - 2), CurParen, SM))
885 PatternStr = PatternStr.
substr(End + 2);
903 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
910 "Invalid substitution block, no ]] found");
916 PatternStr = UnparsedPatternStr.
substr(End + 2);
918 bool IsDefinition =
false;
919 bool SubstNeeded =
false;
922 bool IsLegacyLineExpr =
false;
926 std::string WildcardRegexp;
927 size_t SubstInsertIdx = RegExStr.
size();
931 size_t VarEndIdx = MatchStr.
find(
':');
943 if (!ParseVarResult) {
948 bool IsPseudo = ParseVarResult->IsPseudo;
951 SubstNeeded = !IsDefinition;
956 "invalid name in string variable definition");
962 if (Context->GlobalNumericVariableTable.contains(Name)) {
965 "numeric variable with name '" + Name +
"' already exists");
969 MatchRegexp = MatchStr;
972 MatchStr = OrigMatchStr;
973 IsLegacyLineExpr = IsNumBlock =
true;
975 if (!MatchStr.
empty()) {
978 "invalid name in string variable use");
987 std::unique_ptr<Expression> ExpressionPointer;
988 std::optional<NumericVariable *> DefinedNumericVariable;
992 IsLegacyLineExpr, LineNumber, Context,
999 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
1000 if (DefinedNumericVariable) {
1001 IsDefinition =
true;
1002 DefName = (*DefinedNumericVariable)->getName();
1005 SubstStr = MatchStr;
1009 MatchRegexp = WildcardRegexp;
1019 NumericVariableMatch NumericVariableDefinition = {
1020 *DefinedNumericVariable, CurParen};
1021 NumericVariableDefs[DefName] = NumericVariableDefinition;
1026 Context->GlobalNumericVariableTable[DefName] =
1027 *DefinedNumericVariable;
1029 VariableDefs[DefName] = CurParen;
1036 Context->DefinedVariableTable[DefName] =
true;
1042 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1055 (It = VariableDefs.find(SubstStr)) != VariableDefs.end()) {
1056 unsigned CaptureParenGroup = It->second;
1057 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1060 "Can't back-reference more than 9 variables");
1063 AddBackrefToRegEx(CaptureParenGroup);
1069 ? Context->makeNumericSubstitution(
1070 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1071 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1081 size_t FixedMatchEnd =
1082 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1084 PatternStr = PatternStr.
substr(FixedMatchEnd);
1087 if (MatchFullLinesHere) {
1099 if (!R.isValid(
Error)) {
1101 "invalid regex: " +
Error);
1105 RegExStr += RS.
str();
1106 CurParen += R.getNumMatches();
1110void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1111 assert(BackrefNum >= 1 && BackrefNum <= 9 &&
"Invalid backref number");
1112 std::string Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1113 RegExStr += Backref;
1123 if (!FixedStr.empty()) {
1137 if (!Substitutions.empty()) {
1140 Context->LineVariable->setValue(
1141 APInt(
sizeof(*LineNumber) * 8, *LineNumber));
1143 size_t InsertOffset = 0;
1159 return ErrorDiagnostic::get(
1160 SM, Substitution->getFromString(),
1161 "unable to substitute variable or "
1162 "numeric expression: overflow error");
1165 return ErrorDiagnostic::get(SM, E.getVarName(),
1174 InsertOffset +=
Value->size();
1177 return std::move(Errs);
1180 RegExToMatch = TmpStr;
1187 if (!
Regex(RegExToMatch, Flags).
match(Buffer, &MatchInfo))
1191 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1195 for (
const auto &VariableDef : VariableDefs) {
1196 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1197 Context->GlobalVariableTable[VariableDef.first] =
1198 MatchInfo[VariableDef.second];
1206 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1207 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
1210 for (
const auto &NumericVariableDef : NumericVariableDefs) {
1211 const NumericVariableMatch &NumericVariableMatch =
1212 NumericVariableDef.getValue();
1213 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1214 assert(CaptureParenGroup < MatchInfo.
size() &&
"Internal paren error");
1216 NumericVariableMatch.DefinedNumericVariable;
1218 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1227 Context->GlobalNumericVariableTable.try_emplace(NumericVariableDef.getKey(),
1228 DefinedNumericVariable);
1235unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1243 if (ExampleString.empty())
1244 ExampleString = RegExStr;
1248 BufferPrefix = BufferPrefix.
split(
'\n').first;
1255 std::vector<FileCheckDiag> *Diags)
const {
1257 if (!Substitutions.empty()) {
1265 if (!MatchedValue) {
1272 OS << *MatchedValue;
1279 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1289 std::vector<FileCheckDiag> *Diags)
const {
1290 if (VariableDefs.empty() && NumericVariableDefs.empty())
1298 for (
const auto &VariableDef : VariableDefs) {
1300 VC.Name = VariableDef.first;
1304 VC.Range =
SMRange(Start, End);
1307 for (
const auto &VariableDef : NumericVariableDefs) {
1309 VC.Name = VariableDef.getKey();
1310 std::optional<StringRef> StrValue =
1311 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1316 VC.Range =
SMRange(Start, End);
1321 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1324 assert(
A.Range.Start !=
B.Range.Start &&
1325 "unexpected overlapping variable captures");
1326 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1329 for (
const VarCapture &VC : VarCaptures) {
1332 OS <<
"captured var \"" << VC.Name <<
"\"";
1334 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range, OS.
str());
1343 StringRef Buffer,
size_t Pos,
size_t Len,
1344 std::vector<FileCheckDiag> *Diags,
1345 bool AdjustPrevDiags =
false) {
1350 if (AdjustPrevDiags) {
1351 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1352 for (
auto I = Diags->rbegin(),
E = Diags->rend();
1353 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
1354 I->MatchTy = MatchTy;
1356 Diags->emplace_back(SM, CheckTy,
Loc, MatchTy,
Range);
1362 std::vector<FileCheckDiag> *Diags)
const {
1367 size_t NumLinesForward = 0;
1369 double BestQuality = 0;
1372 if (
size_t(4096) *
size_t(2048) <
1373 std::min(
size_t(4096), Buffer.
size()) *
1374 std::max(FixedStr.size(), RegExStr.size()))
1378 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1379 if (Buffer[i] ==
'\n')
1384 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1389 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1390 double Quality = Distance + (NumLinesForward / 100.);
1394 BestQuality = Quality;
1406 "possible intended match here");
1415 auto VarIter = GlobalVariableTable.find(VarName);
1416 if (VarIter == GlobalVariableTable.end())
1419 return VarIter->second;
1422template <
class... Types>
1424 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1425 return NumericVariables.back().get();
1429FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1431 Substitutions.push_back(
1432 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1433 return Substitutions.back().get();
1436Substitution *FileCheckPatternContext::makeNumericSubstitution(
1439 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1440 this, ExpressionStr, std::move(Expression), InsertIdx));
1441 return Substitutions.back().get();
1448 size_t BracketDepth = 0;
1450 while (!Str.empty()) {
1451 if (Str.starts_with(
"]]") && BracketDepth == 0)
1453 if (Str[0] ==
'\\') {
1455 Str = Str.substr(2);
1465 if (BracketDepth == 0) {
1468 "missing closing \"]\" for regex variable");
1474 Str = Str.substr(1);
1489 if (
Ptr <= End - 2 &&
Ptr[0] ==
'\r' &&
Ptr[1] ==
'\n') {
1495 if (Req.NoCanonicalizeWhiteSpace || (*
Ptr !=
' ' && *
Ptr !=
'\t')) {
1502 while (
Ptr + 1 != End && (
Ptr[1] ==
' ' ||
Ptr[1] ==
'\t'))
1525 return (
isAlnum(c) || c ==
'-' || c ==
'_');
1529 assert(Count > 0 &&
"zero and negative counts are not supported");
1531 "count supported only for plain CHECK directives");
1537 if (Modifiers.none())
1550 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1558 return "misspelled";
1561 return WithModifiers(
"-COUNT");
1562 return WithModifiers(
"");
1564 return WithModifiers(
"-NEXT");
1566 return WithModifiers(
"-SAME");
1568 return WithModifiers(
"-NOT");
1570 return WithModifiers(
"-DAG");
1572 return WithModifiers(
"-LABEL");
1574 return WithModifiers(
"-EMPTY");
1576 return std::string(Prefix);
1578 return "implicit EOF";
1587static std::pair<Check::FileCheckType, StringRef>
1590 if (Buffer.
size() <= Prefix.size())
1603 -> std::pair<Check::FileCheckType, StringRef> {
1612 Rest = Rest.
ltrim();
1614 Ret.setLiteralMatch();
1618 Rest = Rest.
ltrim();
1628 if (Rest.
front() ==
'{')
1643 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1645 return ConsumeModifiers(
1677static std::pair<Check::FileCheckType, StringRef>
1679 bool Misspelled =
false;
1714 Prefixes.push_back({Prefix, Input.find(Prefix)});
1716 Prefixes.push_back({Prefix, Input.find(Prefix)});
1720 [](
auto A,
auto B) { return A.first.size() > B.first.size(); });
1728 "Buffer must be suffix of Input");
1730 size_t From = Buffer.
data() -
Input.data();
1732 for (
auto &[Prefix, Pos] :
Prefixes) {
1735 Pos =
Input.find(Prefix, From);
1768static std::pair<StringRef, StringRef>
1770 StringRef &Buffer,
unsigned &LineNumber,
1772 while (!Buffer.
empty()) {
1780 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1781 "Prefix doesn't start inside of buffer!");
1782 size_t Loc = Prefix.data() - Buffer.
data();
1785 LineNumber += Skipped.
count(
'\n');
1795 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1799 return {Prefix, AfterSuffix};
1813 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1815 LineVariable = makeNumericVariable(
1817 GlobalNumericVariableTable[LineName] = LineVariable;
1827 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1828 if (ImpPatBufferIDRange)
1829 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1832 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1838 PatternContext->createLineVariable();
1840 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1841 for (
StringRef PatternString : Req.ImplicitCheckNot) {
1844 std::string Prefix =
"-implicit-check-not='";
1845 std::string Suffix =
"'";
1847 (Prefix + PatternString + Suffix).str(),
"command line");
1850 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1852 if (ImpPatBufferIDRange) {
1853 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1854 ImpPatBufferIDRange->first = BufferID;
1855 ImpPatBufferIDRange->second = BufferID + 1;
1857 assert(BufferID == ImpPatBufferIDRange->second &&
1858 "expected consecutive source buffer IDs");
1859 ++ImpPatBufferIDRange->second;
1863 ImplicitNegativeChecks.emplace_back(
1866 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1867 PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
1870 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1871 ImplicitNegativeChecks;
1874 unsigned LineNumber = 1;
1877 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1878 std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),
1879 Req.CheckPrefixes.end());
1880 const size_t DistinctPrefixes = PrefixesNotFound.size();
1887 std::tie(UsedPrefix, AfterSuffix) =
1889 if (UsedPrefix.
empty())
1892 PrefixesNotFound.erase(UsedPrefix);
1895 "Failed to move Buffer's start forward, or pointed prefix outside "
1899 "Parsing after suffix doesn't start inside of buffer!");
1902 const char *UsedPrefixStart = UsedPrefix.
data();
1912 AfterSuffix.
data() - UsedPrefix.
data());
1915 "misspelled directive '" + UsedDirective +
"'");
1922 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1929 "invalid count in -COUNT specification on prefix '" +
1936 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1947 Buffer = Buffer.
substr(EOL);
1954 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1955 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1962 "found '" + UsedPrefix +
"-LABEL:'"
1963 " with variable definition or use");
1970 CheckStrings.empty()) {
1976 "found '" + UsedPrefix +
"-" +
Type +
1977 "' without previous '" + UsedPrefix +
": line");
1983 DagNotMatches.emplace_back(
P, UsedPrefix);
1988 CheckStrings.emplace_back(std::move(
P), UsedPrefix, PatternLoc,
1989 std::move(DagNotMatches));
1990 DagNotMatches = ImplicitNegativeChecks;
1995 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1996 const bool SomePrefixesUnexpectedlyNotUsed =
1997 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
1998 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1999 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
2000 errs() <<
"error: no check strings found with prefix"
2001 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
2003 for (
StringRef MissingPrefix : PrefixesNotFound) {
2006 errs() <<
"\'" << MissingPrefix <<
":'";
2015 if (!DagNotMatches.empty()) {
2016 CheckStrings.emplace_back(
2019 std::move(DagNotMatches));
2032 std::vector<FileCheckDiag> *Diags) {
2034 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2035 bool PrintDiag =
true;
2059 assert(!HasError &&
"expected to report more diagnostics for error");
2064 std::string Message =
formatv(
"{0}: {1} string found in input",
2066 (ExpectedMatch ?
"expected" :
"excluded"))
2069 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2086 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2087 FileCheckDiag::MatchFoundErrorNote,
2088 E.getRange(), E.getMessage().str());
2100 bool VerboseVerbose,
2101 std::vector<FileCheckDiag> *Diags) {
2103 bool HasError = ExpectedMatch;
2104 bool HasPatternError =
false;
2110 std::move(MatchError),
2112 HasError = HasPatternError =
true;
2122 bool PrintDiag =
true;
2124 if (!VerboseVerbose)
2140 Buffer, 0, Buffer.
size(), Diags);
2144 Diags->emplace_back(SM, Pat.
getCheckTy(),
Loc, MatchTy, NoteRange,
2149 assert(!HasError &&
"expected to report more diagnostics for error");
2155 if (!HasPatternError) {
2156 std::string Message =
formatv(
"{0}: {1} string not found in input",
2158 (ExpectedMatch ?
"expected" :
"excluded"))
2167 "scanning from here");
2185 std::vector<FileCheckDiag> *Diags) {
2187 return printMatch(ExpectedMatch, SM, Prefix,
Loc, Pat, MatchedCount, Buffer,
2188 std::move(MatchResult), Req, Diags);
2189 return printNoMatch(ExpectedMatch, SM, Prefix,
Loc, Pat, MatchedCount, Buffer,
2196 const char *&FirstNewLine) {
2197 unsigned NumNewLines = 0;
2212 if (NumNewLines == 1)
2213 FirstNewLine =
Range.begin();
2218 bool IsLabelScanMode,
size_t &MatchLen,
2220 std::vector<FileCheckDiag> *Diags)
const {
2222 std::vector<const DagNotPrefixInfo *> NotStrings;
2228 if (!IsLabelScanMode) {
2230 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2236 size_t LastMatchEnd = LastPos;
2237 size_t FirstMatchPos = 0;
2240 assert(
Pat.getCount() != 0 &&
"pattern count can not be zero");
2241 for (
int i = 1; i <=
Pat.getCount(); i++) {
2248 Pat, i, MatchBuffer,
2249 std::move(MatchResult), Req, Diags)) {
2254 size_t MatchPos = MatchResult.
TheMatch->Pos;
2256 FirstMatchPos = LastPos + MatchPos;
2259 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2262 MatchLen = LastMatchEnd - FirstMatchPos;
2266 if (!IsLabelScanMode) {
2267 size_t MatchPos = FirstMatchPos - LastPos;
2275 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2284 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2291 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2295 return FirstMatchPos;
2308 const char *FirstNewLine =
nullptr;
2311 if (NumNewLines == 0) {
2313 CheckName +
": is on the same line as previous match");
2315 "'next' match was here");
2317 "previous match ended here");
2321 if (NumNewLines != 1) {
2324 ": is not on the line after the previous match");
2326 "'next' match was here");
2328 "previous match ended here");
2330 "non-matching line after previous match is here");
2342 const char *FirstNewLine =
nullptr;
2345 if (NumNewLines != 0) {
2348 "-SAME: is not on the same line as the previous match");
2350 "'next' match was here");
2352 "previous match ended here");
2361 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2363 bool DirectiveFail =
false;
2364 for (
auto NotInfo : NotStrings) {
2366 "Expect CHECK-NOT!");
2369 false, SM, NotInfo->DagNotPrefix,
2370 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2371 std::move(MatchResult), Req, Diags)) {
2373 DirectiveFail =
true;
2377 return DirectiveFail;
2382 std::vector<const DagNotPrefixInfo *> &NotStrings,
2384 std::vector<FileCheckDiag> *Diags)
const {
2389 size_t StartPos = 0;
2398 std::list<MatchRange> MatchRanges;
2403 PatItr != PatEnd; ++PatItr) {
2405 const StringRef DNPrefix = PatItr->DagNotPrefix;
2408 "Invalid CHECK-DAG or CHECK-NOT!");
2411 NotStrings.push_back(&*PatItr);
2418 size_t MatchLen = 0, MatchPos = StartPos;
2422 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2429 Pat.getLoc(),
Pat, 1, MatchBuffer,
2430 std::move(MatchResult), Req, Diags)) {
2436 MatchLen = MatchResult.
TheMatch->Len;
2439 MatchPos += MatchResult.
TheMatch->Pos;
2440 MatchRange M{MatchPos, MatchPos + MatchLen};
2445 if (MatchRanges.empty())
2446 MatchRanges.insert(MatchRanges.end(), M);
2448 auto Block = MatchRanges.begin();
2455 bool Overlap =
false;
2456 for (;
MI != ME; ++
MI) {
2457 if (M.Pos <
MI->End) {
2460 Overlap =
MI->Pos < M.End;
2466 MatchRanges.insert(
MI, M);
2476 SMRange OldRange(OldStart, OldEnd);
2478 "match discarded, overlaps earlier DAG match here",
2481 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2482 for (
auto I = Diags->rbegin(), E = Diags->rend();
2483 I != E &&
I->CheckLoc == CheckLoc; ++
I)
2491 true, SM, DNPrefix,
Pat.getLoc(),
Pat, 1, Buffer,
2496 if (std::next(PatItr) == PatEnd ||
2498 if (!NotStrings.empty()) {
2503 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2504 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2511 StartPos = MatchRanges.rbegin()->End;
2513 MatchRanges.clear();
2522 for (
StringRef Prefix : SuppliedPrefixes) {
2523 if (Prefix.empty()) {
2524 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2528 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2529 if (!Validator.
match(Prefix)) {
2530 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2531 <<
"letter and contain only alphanumeric characters, hyphens, and "
2532 <<
"underscores: '" << Prefix <<
"'\n";
2535 if (!UniquePrefixes.
insert(Prefix).second) {
2536 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2537 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2547 if (Req.CheckPrefixes.empty())
2549 if (Req.CommentPrefixes.empty())
2562 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2563 "Overriding defined variable with command-line variable definitions");
2565 if (CmdlineDefines.
empty())
2573 std::string CmdlineDefsDiag;
2575 for (
StringRef CmdlineDef : CmdlineDefines) {
2576 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2577 size_t EqIdx = CmdlineDef.find(
'=');
2579 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2583 if (CmdlineDef[0] ==
'#') {
2587 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2588 std::string SubstitutionStr = std::string(CmdlineDef);
2589 SubstitutionStr[EqIdx] =
':';
2591 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2592 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2594 CmdlineDefsDiag += DefPrefix;
2596 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2597 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2604 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2606 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2609 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2610 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2611 CmdlineDefIndices.second);
2612 if (CmdlineDef.
empty()) {
2616 "missing equal sign in global definition"));
2621 if (CmdlineDef[0] ==
'#') {
2625 std::optional<NumericVariable *> DefinedNumericVariable;
2628 DefinedNumericVariable,
false,
2629 std::nullopt,
this, SM);
2630 if (!ExpressionResult) {
2634 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2645 assert(DefinedNumericVariable &&
"No variable defined");
2646 (*DefinedNumericVariable)->setValue(*
Value);
2649 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2650 *DefinedNumericVariable;
2653 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2654 StringRef CmdlineName = CmdlineNameVal.first;
2655 StringRef OrigCmdlineName = CmdlineName;
2658 if (!ParseVarResult) {
2665 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2668 SM, OrigCmdlineName,
2669 "invalid name in string variable definition '" +
2670 OrigCmdlineName +
"'"));
2677 if (GlobalNumericVariableTable.contains(Name)) {
2680 "numeric variable with name '" +
2681 Name +
"' already exists"));
2684 GlobalVariableTable.insert(CmdlineNameVal);
2691 DefinedVariableTable[Name] =
true;
2701 if (Var.first()[0] !=
'$')
2702 LocalPatternVars.
push_back(Var.first());
2710 for (
const auto &Var : GlobalNumericVariableTable)
2711 if (Var.first()[0] !=
'$') {
2712 Var.getValue()->clearValue();
2713 LocalNumericVars.
push_back(Var.first());
2716 for (
const auto &Var : LocalPatternVars)
2717 GlobalVariableTable.erase(Var);
2718 for (
const auto &Var : LocalNumericVars)
2719 GlobalNumericVariableTable.erase(Var);
2723 std::vector<FileCheckDiag> *Diags) {
2724 bool ChecksFailed =
false;
2726 unsigned i = 0, j = 0, e = CheckStrings.size();
2730 CheckRegion = Buffer;
2739 size_t MatchLabelLen = 0;
2740 size_t MatchLabelPos =
2741 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2746 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2747 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2754 if (i != 0 && Req.EnableVarScope)
2755 PatternContext->clearLocalVars();
2757 for (; i != j; ++i) {
2762 size_t MatchLen = 0;
2764 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2767 ChecksFailed =
true;
2772 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2780 return !ChecksFailed;
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, PrefixMatcher &Matcher, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
static size_t SkipWord(StringRef Str, size_t Loc)
static char popFront(StringRef &S)
constexpr StringLiteral SpaceChars
static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported.
static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Error MatchError, bool VerboseVerbose, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported,...
static std::pair< Check::FileCheckType, StringRef > FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix, bool &Misspelled)
static const char * DefaultCheckPrefixes[]
static const char * DefaultCommentPrefixes[]
static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy, const SourceMgr &SM, SMLoc Loc, Check::FileCheckType CheckTy, StringRef Buffer, size_t Pos, size_t Len, std::vector< FileCheckDiag > *Diags, bool AdjustPrevDiags=false)
static unsigned CountNumNewlinesBetween(StringRef Range, const char *&FirstNewLine)
Counts the number of newlines in the specified range.
static APInt toSigned(APInt AbsVal, bool Negative)
static Error printMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error or (2) ErrorReported if an error was reported,...
static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, ArrayRef< StringRef > SuppliedPrefixes)
static void addDefaultPrefixes(FileCheckRequest &Req)
static unsigned nextAPIntBitWidth(unsigned BitWidth)
static bool IsPartOfWord(char c)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
APInt abs() const
Get the absolute value.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
static constexpr unsigned APINT_BITS_PER_WORD
Bits in a word.
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
bool slt(const APInt &RHS) const
Signed less than comparison.
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI void toString(SmallVectorImpl< char > &Str, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false) const
Converts an APInt to a string and append it to Str.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
Expected< ExpressionFormat > getImplicitFormat(const SourceMgr &SM) const override
Expected< APInt > eval() const override
Evaluates the value of the binary operation represented by this AST, using EvalBinop on the result of...
LLVM_ABI std::string getDescription(StringRef Prefix) const
bool isLiteralMatch() const
LLVM_ABI std::string getModifiersDescription() const
LLVM_ABI FileCheckType & setCount(int C)
Class to represent an error holding a diagnostic with location information used when printing it.
static LLVM_ABI_FOR_TEST char ID
static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg, SMRange Range=std::nullopt)
An error that has already been reported.
static Error reportedOrSuccess(bool HasErrorReported)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
virtual Expected< APInt > eval() const =0
Evaluates and.
StringRef getExpressionStr() const
Class representing an expression and its matching format.
ExpressionAST * getAST() const
Class holding the Pattern global state, shared by all patterns: tables holding values of variables an...
LLVM_ABI_FOR_TEST Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
LLVM_ABI_FOR_TEST void createLineVariable()
Create @LINE pseudo variable.
LLVM_ABI_FOR_TEST Expected< StringRef > getPatternVarValue(StringRef VarName)
LLVM_ABI_FOR_TEST void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
LLVM_ABI bool readCheckFile(SourceMgr &SM, StringRef Buffer, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
LLVM_ABI StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
LLVM_ABI FileCheck(FileCheckRequest Req)
LLVM_ABI bool checkInput(SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags=nullptr)
Checks the input to FileCheck provided in the Buffer against the expected strings read from the check...
LLVM_ABI bool ValidateCheckPrefixes()
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
const char * getBufferEnd() const
const char * getBufferStart() const
static LLVM_ABI_FOR_TEST char ID
Expected< std::string > getResultForDiagnostics() const override
Expected< std::string > getResultRegex() const override
Expected< APInt > eval() const override
Class representing a numeric variable and its associated current value.
void setValue(APInt NewValue, std::optional< StringRef > NewStrValue=std::nullopt)
Sets value of this numeric variable to NewValue, and sets the input buffer string from which it was p...
ExpressionFormat getImplicitFormat() const
std::optional< size_t > getDefLineNumber() const
Class to represent an overflow error that might result when manipulating a value.
static LLVM_ABI_FOR_TEST char ID
This class represents success/failure for parsing-like operations that find it important to chain tog...
static LLVM_ABI_FOR_TEST Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags) const
void printSubstitutions(const SourceMgr &SM, StringRef Buffer, SMRange MatchRange, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
Prints the value of successful substitutions.
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< Expression > > parseNumericSubstitutionBlock(StringRef Expr, std::optional< NumericVariable * > &DefinedNumericVariable, bool IsLegacyLineExpr, std::optional< size_t > LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM)
Parses Expr for a numeric substitution block at line LineNumber, or before input is parsed if LineNum...
LLVM_ABI_FOR_TEST void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
static LLVM_ABI_FOR_TEST bool isValidVarNameStart(char C)
Check::FileCheckType getCheckTy() const
LLVM_ABI_FOR_TEST bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, const FileCheckRequest &Req)
Parses the pattern in PatternStr and initializes this Pattern instance accordingly.
@ Newline
Compile for newline-sensitive matching.
@ IgnoreCase
Compile for matching that ignores upper/lower case distinctions.
static LLVM_ABI std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI std::pair< unsigned, unsigned > getLineAndColumn(SMLoc Loc, unsigned BufferID=0) const
Find the line and column number for the specified location in the specified file.
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
LLVM_ABI unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
char back() const
back - Get the last character in the string.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
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.
size_t count(char C) const
Return the number of occurrences of C in the string.
static constexpr size_t npos
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
StringSet - A wrapper for StringMap that provides set-like functionality.
void insert_range(Range &&R)
std::pair< typename Base::iterator, bool > insert(StringRef key)
Expected< std::string > getResultRegex() const override
Expected< std::string > getResultForDiagnostics() const override
Class representing a substitution to perform in the RegExStr string.
StringRef getFromString() const
FileCheckPatternContext * Context
Pointer to a class instance holding, among other things, the table with the values of live string var...
virtual Expected< std::string > getResultRegex() const =0
virtual Expected< std::string > getResultForDiagnostics() const =0
StringRef FromStr
The string that needs to be substituted for something else.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
Class to represent an undefined variable error, which quotes that variable's name when printed.
static LLVM_ABI_FOR_TEST char ID
LLVM Value Representation.
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
@ CheckBadNot
Marks when parsing found a -NOT check combined with another CHECK suffix.
@ CheckBadCount
Marks when parsing found a -COUNT directive with invalid count value.
@ CheckEOF
Indicates the pattern only matches the end of file.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
LLVM_ABI_FOR_TEST Expected< APInt > exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Performs operation and.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Expected< APInt >(*)(const APInt &, const APInt &, bool &) binop_eval_t
Type of functions evaluating a given binary operation.
bool isAlpha(char C)
Checks if character C is a valid letter as classified by "C" locale.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
FunctionAddr VTableAddr Count
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
constexpr unsigned BitWidth
bool isPrint(char C)
Checks whether character C is printable.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Expected< APInt > exprMax(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI_FOR_TEST Expected< APInt > exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Expected< APInt > exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI_FOR_TEST Expected< APInt > exprSub(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
StringRef match(StringRef Buffer)
Find the next match of a prefix in Buffer.
SmallVector< std::pair< StringRef, size_t > > Prefixes
Prefixes and their first occurrence past the current position.
PrefixMatcher(ArrayRef< StringRef > CheckPrefixes, ArrayRef< StringRef > CommentPrefixes, StringRef Input)
std::string Note
A note to replace the one normally indicated by MatchTy, or the empty string if none.
enum llvm::FileCheckDiag::MatchType MatchTy
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
LLVM_ABI FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange, StringRef Note="")
Check::FileCheckType CheckTy
What is the FileCheck directive for this diagnostic?
MatchType
What type of match result does this diagnostic describe?
@ MatchFoundButWrongLine
Indicates a match for an expected pattern, but the match is on the wrong line.
@ MatchNoneAndExcluded
Indicates no match for an excluded pattern.
@ MatchFoundButExcluded
Indicates a match for an excluded pattern.
@ MatchFuzzy
Indicates a fuzzy match that serves as a suggestion for the next intended match for an expected patte...
@ MatchFoundButDiscarded
Indicates a discarded match for an expected pattern.
@ MatchNoneForInvalidPattern
Indicates no match due to an expected or excluded pattern that has proven to be invalid at match time...
@ MatchFoundAndExpected
Indicates a good match for an expected pattern.
@ MatchNoneButExpected
Indicates no match for an expected pattern, but this might follow good matches when multiple matches ...
SMLoc CheckLoc
Where is the FileCheck directive for this diagnostic?
Contains info about various FileCheck options.
bool IsDefaultCheckPrefix
bool NoCanonicalizeWhiteSpace
std::vector< StringRef > CommentPrefixes
std::vector< StringRef > CheckPrefixes
bool AllowDeprecatedDagOverlap
A check that we found in the input file.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is a single line in the given Buffer.
Pattern Pat
The pattern to match.
bool CheckSame(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is no newline in the given Buffer.
std::vector< DagNotPrefixInfo > DagNotStrings
Hold the DAG/NOT strings occurring in the input file.
SMLoc Loc
The location in the match file that the check string was specified.
StringRef Prefix
Which prefix name this check matched.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches "dag strings" and their mixed "not strings".
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, size_t &MatchLen, FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches check string and its "not strings" and/or "dag strings".
bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
std::optional< Match > TheMatch
Parsing information about a variable.