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");
91 AbsoluteValue = *SignedValue;
96 AbsoluteValue = *UnsignedValue;
99 std::string AbsoluteValueStr;
103 AbsoluteValueStr = utostr(AbsoluteValue);
111 "trying to match value with invalid format");
116 if (Precision > AbsoluteValueStr.size()) {
117 unsigned LeadingZeros = Precision - AbsoluteValueStr.size();
118 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
119 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
123 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
136 StringRef IntegerParseErrorStr =
"unable to represent numeric value";
140 if (StrVal.getAsInteger(10, SignedValue))
148 bool MissingFormPrefix = AlternateForm && !StrVal.consume_front(
"0x");
149 (void)MissingFormPrefix;
150 assert(!MissingFormPrefix &&
"missing alternate form prefix");
151 if (StrVal.getAsInteger(Hex ? 16 : 10, UnsignedValue))
163 memcpy(&SignedValue, &UnsignedValue,
sizeof(SignedValue));
172 return make_error<OverflowError>();
175 return static_cast<int64_t
>(
Value);
180 return make_error<OverflowError>();
190 int64_t MaxInt64 = std::numeric_limits<int64_t>::max();
192 if (SignedValue >= -MaxInt64)
196 SignedValue += MaxInt64;
197 uint64_t RemainingValueAbsolute = -SignedValue;
206 std::optional<int64_t> Result = checkedAdd<int64_t>(LeftValue, RightValue);
208 return make_error<OverflowError>();
224 std::optional<uint64_t> Result =
225 checkedAddUnsigned<uint64_t>(LeftValue, RightValue);
227 return make_error<OverflowError>();
239 if (RightValue > (
uint64_t)std::numeric_limits<int64_t>::max())
240 return make_error<OverflowError>();
241 std::optional<int64_t> Result =
242 checkedSub(LeftValue,
static_cast<int64_t
>(RightValue));
244 return make_error<OverflowError>();
260 if (LeftValue >= RightValue)
264 uint64_t MaxInt64 = std::numeric_limits<int64_t>::max();
268 int64_t Result = -MaxInt64;
269 int64_t MinInt64 = std::numeric_limits<int64_t>::min();
273 return make_error<OverflowError>();
290 return RightOperand * LeftOperand;
306 std::optional<uint64_t> Result =
307 checkedMulUnsigned<uint64_t>(LeftValue, RightValue);
309 return make_error<OverflowError>();
322 return make_error<OverflowError>();
356 if (
cantFail(
max(LeftOperand, RightOperand)) == LeftOperand)
376 if (!LeftOp || !RightOp) {
382 return std::move(Err);
385 return EvalBinop(*LeftOp, *RightOp);
392 if (!LeftFormat || !RightFormat) {
398 return std::move(Err);
403 *LeftFormat != *RightFormat)
406 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
407 "' (" + LeftFormat->toString() +
") and '" +
408 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
409 "), need an explicit format specifier");
416 assert(ExpressionPointer->getAST() !=
nullptr &&
417 "Substituting empty expression");
419 ExpressionPointer->getAST()->eval();
423 return Format.getMatchingString(*EvaluatedValue);
442 bool IsPseudo = Str[0] ==
'@';
445 if (Str[0] ==
'$' || IsPseudo)
451 for (
size_t E = Str.size();
I !=
E; ++
I)
453 if (Str[
I] !=
'_' && !isAlnum(Str[
I]))
487 if (ParseVarResult->IsPseudo)
489 SM,
Name,
"definition of pseudo numeric variable unsupported");
495 SM,
Name,
"string variable with name '" +
Name +
"' already exists");
500 SM, Expr,
"unexpected characters after numeric variable name");
503 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
504 if (VarTableIter !=
Context->GlobalNumericVariableTable.end()) {
505 DefinedNumericVariable = VarTableIter->second;
508 SM, Expr,
"format different from previous variable definition");
510 DefinedNumericVariable =
511 Context->makeNumericVariable(
Name, ImplicitFormat, LineNumber);
513 return DefinedNumericVariable;
517 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
519 if (IsPseudo && !
Name.equals(
"@LINE"))
521 SM,
Name,
"invalid pseudo numeric variable '" +
Name +
"'");
531 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
533 if (VarTableIter !=
Context->GlobalNumericVariableTable.end())
542 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
545 "numeric variable '" +
Name +
546 "' defined earlier in the same CHECK directive");
552 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
556 if (AO != AllowedOperand::Any)
558 SM, Expr,
"parenthesized expression not permitted here");
559 return parseParenExpr(Expr, LineNumber, Context, SM);
562 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
566 if (ParseVarResult) {
569 if (AO != AllowedOperand::Any)
571 "unexpected function call");
573 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
577 return parseNumericVariableUse(ParseVarResult->Name,
578 ParseVarResult->IsPseudo, LineNumber,
582 if (AO == AllowedOperand::LineVar)
589 int64_t SignedLiteralValue;
593 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
594 UnsignedLiteralValue))
595 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
596 UnsignedLiteralValue);
598 if (AO == AllowedOperand::Any && !Expr.
consumeInteger(0, SignedLiteralValue))
599 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
605 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
610Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
623 Expr, AllowedOperand::Any,
false, LineNumber,
628 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
629 LineNumber, Context, SM);
633 return SubExprResult;
637 "missing ')' at end of nested expression");
639 return SubExprResult;
644 std::unique_ptr<ExpressionAST> LeftOp,
645 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
648 if (RemainingExpr.
empty())
649 return std::move(LeftOp);
658 EvalBinop =
operator+;
661 EvalBinop =
operator-;
670 if (RemainingExpr.
empty())
672 "missing operand in expression");
675 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
677 parseNumericOperand(RemainingExpr, AO,
false,
678 LineNumber, Context, SM);
680 return RightOpResult;
683 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
684 std::move(*RightOpResult));
689 std::optional<size_t> LineNumber,
695 .
Case(
"add",
operator+)
696 .
Case(
"div",
operator/)
699 .
Case(
"mul",
operator*)
700 .
Case(
"sub",
operator-)
705 SM, FuncName,
Twine(
"call to undefined function '") + FuncName +
"'");
719 Expr, AllowedOperand::Any,
false, LineNumber,
728 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*
Arg),
false, LineNumber,
734 return Arg.takeError();
735 Args.push_back(std::move(*
Arg));
749 "missing ')' at end of call expression");
751 const unsigned NumArgs =
Args.size();
753 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
758 Twine(
"function '") + FuncName +
759 Twine(
"' takes 2 arguments but ") +
760 Twine(NumArgs) +
" given");
764 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
765 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
767 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
769 DefinedNumericVariable = std::nullopt;
771 unsigned Precision = 0;
774 size_t FormatSpecEnd = Expr.
find(
',');
775 size_t FunctionStart = Expr.
find(
'(');
776 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
783 "invalid matching format specification in expression");
793 "invalid precision in format specifier");
796 if (!FormatExpr.
empty()) {
811 Precision, AlternateForm);
815 Precision, AlternateForm);
819 "invalid format specifier in expression");
826 SM, AlternateFormFlagLoc,
827 "alternate form only supported for hex values");
830 if (!FormatExpr.
empty())
833 "invalid matching format specification in expression");
837 size_t DefEnd = Expr.
find(
':');
839 DefExpr = Expr.
substr(0, DefEnd);
840 Expr = Expr.
substr(DefEnd + 1);
845 bool HasParsedValidConstraint =
false;
847 HasParsedValidConstraint =
true;
852 if (HasParsedValidConstraint)
854 SM, Expr,
"empty numeric expression should not have a constraint");
861 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
863 Expr, AO, !HasParsedValidConstraint, LineNumber,
Context, SM);
864 while (ParseResult && !Expr.
empty()) {
865 ParseResult = parseBinop(OuterBinOpExpr, Expr, std::move(*ParseResult),
866 IsLegacyLineExpr, LineNumber,
Context, SM);
868 if (ParseResult && IsLegacyLineExpr && !Expr.
empty())
871 "unexpected characters at end of expression '" + Expr +
"'");
875 ExpressionASTPointer = std::move(*ParseResult);
885 else if (ExpressionASTPointer) {
887 ExpressionASTPointer->getImplicitFormat(SM);
895 std::unique_ptr<Expression> ExpressionPointer =
896 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
902 DefExpr,
Context, LineNumber, ExpressionPointer->getFormat(), SM);
906 DefinedNumericVariable = *ParseResult;
909 return std::move(ExpressionPointer);
921 while (!PatternStr.
empty() &&
922 (PatternStr.
back() ==
' ' || PatternStr.
back() ==
'\t'))
923 PatternStr = PatternStr.
substr(0, PatternStr.
size() - 1);
928 "found empty check string with prefix '" + Prefix +
":'");
935 "found non-empty check string for empty check with prefix '" + Prefix +
947 FixedStr = PatternStr;
952 if (!MatchFullLinesHere &&
953 (PatternStr.
size() < 2 ||
955 FixedStr = PatternStr;
959 if (MatchFullLinesHere) {
967 unsigned CurParen = 1;
971 while (!PatternStr.
empty()) {
975 size_t End = PatternStr.
find(
"}}");
979 "found start of regex string with no end '}}'");
990 if (AddRegExToRegEx(PatternStr.
substr(2,
End - 2), CurParen, SM))
1012 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
1019 "Invalid substitution block, no ]] found");
1025 PatternStr = UnparsedPatternStr.
substr(
End + 2);
1027 bool IsDefinition =
false;
1028 bool SubstNeeded =
false;
1031 bool IsLegacyLineExpr =
false;
1035 std::string WildcardRegexp;
1036 size_t SubstInsertIdx = RegExStr.size();
1040 size_t VarEndIdx = MatchStr.
find(
':');
1052 if (!ParseVarResult) {
1057 bool IsPseudo = ParseVarResult->IsPseudo;
1060 SubstNeeded = !IsDefinition;
1065 "invalid name in string variable definition");
1071 if (
Context->GlobalNumericVariableTable.contains(
Name)) {
1074 "numeric variable with name '" +
Name +
"' already exists");
1078 MatchRegexp = MatchStr;
1081 MatchStr = OrigMatchStr;
1082 IsLegacyLineExpr = IsNumBlock =
true;
1084 if (!MatchStr.
empty()) {
1087 "invalid name in string variable use");
1096 std::unique_ptr<Expression> ExpressionPointer;
1097 std::optional<NumericVariable *> DefinedNumericVariable;
1101 IsLegacyLineExpr, LineNumber,
Context,
1107 ExpressionPointer = std::move(*ParseResult);
1108 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
1109 if (DefinedNumericVariable) {
1110 IsDefinition =
true;
1111 DefName = (*DefinedNumericVariable)->getName();
1114 SubstStr = MatchStr;
1118 MatchRegexp = WildcardRegexp;
1128 NumericVariableMatch NumericVariableDefinition = {
1129 *DefinedNumericVariable, CurParen};
1130 NumericVariableDefs[DefName] = NumericVariableDefinition;
1135 Context->GlobalNumericVariableTable[DefName] =
1136 *DefinedNumericVariable;
1138 VariableDefs[DefName] = CurParen;
1145 Context->DefinedVariableTable[DefName] =
true;
1151 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1162 if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
1163 unsigned CaptureParenGroup = VariableDefs[SubstStr];
1164 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1167 "Can't back-reference more than 9 variables");
1170 AddBackrefToRegEx(CaptureParenGroup);
1176 ?
Context->makeNumericSubstitution(
1177 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1178 :
Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1188 size_t FixedMatchEnd =
1189 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1191 PatternStr = PatternStr.
substr(FixedMatchEnd);
1194 if (MatchFullLinesHere) {
1206 if (!R.isValid(
Error)) {
1208 "invalid regex: " +
Error);
1212 RegExStr += RS.
str();
1213 CurParen += R.getNumMatches();
1217void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1218 assert(BackrefNum >= 1 && BackrefNum <= 9 &&
"Invalid backref number");
1219 std::string Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1220 RegExStr += Backref;
1230 if (!FixedStr.
empty()) {
1234 return make_error<NotFoundError>();
1244 if (!Substitutions.empty()) {
1249 size_t InsertOffset = 0;
1265 return ErrorDiagnostic::get(
1266 SM, Substitution->getFromString(),
1267 "unable to substitute variable or "
1268 "numeric expression: overflow error");
1271 return ErrorDiagnostic::get(SM, E.getVarName(),
1280 InsertOffset +=
Value->size();
1283 return std::move(Errs);
1286 RegExToMatch = TmpStr;
1294 return make_error<NotFoundError>();
1297 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1301 for (
const auto &VariableDef : VariableDefs) {
1302 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1303 Context->GlobalVariableTable[VariableDef.first] =
1304 MatchInfo[VariableDef.second];
1312 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1313 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
1316 for (
const auto &NumericVariableDef : NumericVariableDefs) {
1317 const NumericVariableMatch &NumericVariableMatch =
1318 NumericVariableDef.getValue();
1319 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1320 assert(CaptureParenGroup < MatchInfo.
size() &&
"Internal paren error");
1322 NumericVariableMatch.DefinedNumericVariable;
1324 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1327 Format.valueFromStringRepr(MatchedValue, SM);
1336unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1344 if (ExampleString.empty())
1345 ExampleString = RegExStr;
1349 BufferPrefix = BufferPrefix.
split(
'\n').first;
1356 std::vector<FileCheckDiag> *Diags)
const {
1358 if (!Substitutions.empty()) {
1365 if (!MatchedValue) {
1379 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1380 SMRange(Range.Start, Range.Start),
OS.str());
1389 std::vector<FileCheckDiag> *Diags)
const {
1390 if (VariableDefs.empty() && NumericVariableDefs.
empty())
1398 for (
const auto &VariableDef : VariableDefs) {
1400 VC.Name = VariableDef.first;
1407 for (
const auto &VariableDef : NumericVariableDefs) {
1409 VC.Name = VariableDef.getKey();
1410 std::optional<StringRef> StrValue =
1411 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1421 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1424 assert(
A.Range.Start !=
B.Range.Start &&
1425 "unexpected overlapping variable captures");
1426 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1429 for (
const VarCapture &VC : VarCaptures) {
1432 OS <<
"captured var \"" << VC.Name <<
"\"";
1434 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range,
OS.str());
1443 StringRef Buffer,
size_t Pos,
size_t Len,
1444 std::vector<FileCheckDiag> *Diags,
1445 bool AdjustPrevDiags =
false) {
1450 if (AdjustPrevDiags) {
1451 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1452 for (
auto I = Diags->rbegin(),
E = Diags->rend();
1453 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
1454 I->MatchTy = MatchTy;
1456 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
1462 std::vector<FileCheckDiag> *Diags)
const {
1467 size_t NumLinesForward = 0;
1469 double BestQuality = 0;
1472 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1473 if (Buffer[i] ==
'\n')
1478 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1483 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1484 double Quality = Distance + (NumLinesForward / 100.);
1488 BestQuality = Quality;
1500 "possible intended match here");
1509 auto VarIter = GlobalVariableTable.find(VarName);
1510 if (VarIter == GlobalVariableTable.end())
1511 return make_error<UndefVarError>(VarName);
1513 return VarIter->second;
1516template <
class... Types>
1518 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1519 return NumericVariables.back().get();
1523FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1525 Substitutions.push_back(
1526 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1527 return Substitutions.back().get();
1530Substitution *FileCheckPatternContext::makeNumericSubstitution(
1533 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1534 this, ExpressionStr, std::move(
Expression), InsertIdx));
1535 return Substitutions.back().get();
1542 size_t BracketDepth = 0;
1544 while (!Str.empty()) {
1545 if (Str.startswith(
"]]") && BracketDepth == 0)
1547 if (Str[0] ==
'\\') {
1549 Str = Str.substr(2);
1559 if (BracketDepth == 0) {
1562 "missing closing \"]\" for regex variable");
1568 Str = Str.substr(1);
1583 if (
Ptr <=
End - 2 &&
Ptr[0] ==
'\r' &&
Ptr[1] ==
'\n') {
1596 while (
Ptr + 1 !=
End && (
Ptr[1] ==
' ' ||
Ptr[1] ==
'\t'))
1609 : CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy),
Note(
Note) {
1619 return (isAlnum(c) || c ==
'-' || c ==
'_');
1623 assert(Count > 0 &&
"zero and negative counts are not supported");
1625 "count supported only for plain CHECK directives");
1631 if (Modifiers.none())
1636 if (isLiteralMatch())
1644 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1645 return (Prefix + Str + getModifiersDescription()).str();
1652 return "misspelled";
1655 return WithModifiers(
"-COUNT");
1656 return WithModifiers(
"");
1658 return WithModifiers(
"-NEXT");
1660 return WithModifiers(
"-SAME");
1662 return WithModifiers(
"-NOT");
1664 return WithModifiers(
"-DAG");
1666 return WithModifiers(
"-LABEL");
1668 return WithModifiers(
"-EMPTY");
1670 return std::string(Prefix);
1672 return "implicit EOF";
1681static std::pair<Check::FileCheckType, StringRef>
1684 if (Buffer.
size() <= Prefix.size())
1697 -> std::pair<Check::FileCheckType, StringRef> {
1706 Rest = Rest.
ltrim();
1708 Ret.setLiteralMatch();
1712 Rest = Rest.
ltrim();
1722 if (Rest.
front() ==
'{')
1735 if (Count <= 0 || Count > INT32_MAX)
1737 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1739 return ConsumeModifiers(
1771static std::pair<Check::FileCheckType, StringRef>
1773 bool Misspelled =
false;
1810static std::pair<StringRef, StringRef>
1812 StringRef &Buffer,
unsigned &LineNumber,
1816 while (!Buffer.
empty()) {
1818 if (!PrefixRE.
match(Buffer, &Matches))
1826 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1827 "Prefix doesn't start inside of buffer!");
1828 size_t Loc = Prefix.data() - Buffer.
data();
1831 LineNumber += Skipped.
count(
'\n');
1841 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1845 return {Prefix, AfterSuffix};
1859 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1861 LineVariable = makeNumericVariable(
1863 GlobalNumericVariableTable[LineName] = LineVariable;
1874 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1875 if (ImpPatBufferIDRange)
1876 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1879 PatternContext->defineCmdlineVariables(Req.
GlobalDefines, SM);
1885 PatternContext->createLineVariable();
1887 std::vector<Pattern> ImplicitNegativeChecks;
1891 std::string Prefix =
"-implicit-check-not='";
1892 std::string Suffix =
"'";
1894 (Prefix + PatternString + Suffix).str(),
"command line");
1897 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1899 if (ImpPatBufferIDRange) {
1900 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1901 ImpPatBufferIDRange->first = BufferID;
1902 ImpPatBufferIDRange->second = BufferID + 1;
1904 assert(BufferID == ImpPatBufferIDRange->second &&
1905 "expected consecutive source buffer IDs");
1906 ++ImpPatBufferIDRange->second;
1910 ImplicitNegativeChecks.push_back(
1912 ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
1913 "IMPLICIT-CHECK", SM, Req);
1916 std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
1920 unsigned LineNumber = 1;
1922 std::set<StringRef> PrefixesNotFound(Req.
CheckPrefixes.begin(),
1924 const size_t DistinctPrefixes = PrefixesNotFound.size();
1931 std::tie(UsedPrefix, AfterSuffix) =
1933 if (UsedPrefix.
empty())
1936 PrefixesNotFound.erase(UsedPrefix);
1939 "Failed to move Buffer's start forward, or pointed prefix outside "
1943 "Parsing after suffix doesn't start inside of buffer!");
1946 const char *UsedPrefixStart = UsedPrefix.
data();
1956 AfterSuffix.
data() - UsedPrefix.
data());
1959 "misspelled directive '" + UsedDirective +
"'");
1966 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1973 "invalid count in -COUNT specification on prefix '" +
1991 Buffer = Buffer.
substr(EOL);
1998 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1999 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
2006 "found '" + UsedPrefix +
"-LABEL:'"
2007 " with variable definition or use");
2014 CheckStrings->empty()) {
2020 "found '" + UsedPrefix +
"-" +
Type +
2021 "' without previous '" + UsedPrefix +
": line");
2027 DagNotMatches.push_back(
P);
2032 CheckStrings->emplace_back(
P, UsedPrefix, PatternLoc);
2033 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
2034 DagNotMatches = ImplicitNegativeChecks;
2039 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
2040 const bool SomePrefixesUnexpectedlyNotUsed =
2042 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
2044 errs() <<
"error: no check strings found with prefix"
2045 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
2047 for (
StringRef MissingPrefix : PrefixesNotFound) {
2050 errs() <<
"\'" << MissingPrefix <<
":'";
2059 if (!DagNotMatches.empty()) {
2060 CheckStrings->emplace_back(
2063 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
2076 std::vector<FileCheckDiag> *Diags) {
2078 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2079 bool PrintDiag =
true;
2103 assert(!HasError &&
"expected to report more diagnostics for error");
2108 std::string Message =
formatv(
"{0}: {1} string found in input",
2110 (ExpectedMatch ?
"expected" :
"excluded"))
2113 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2130 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2131 FileCheckDiag::MatchFoundErrorNote,
2132 E.getRange(), E.getMessage().str());
2144 bool VerboseVerbose,
2145 std::vector<FileCheckDiag> *Diags) {
2147 bool HasError = ExpectedMatch;
2148 bool HasPatternError =
false;
2154 std::move(MatchError),
2156 HasError = HasPatternError =
true;
2166 bool PrintDiag =
true;
2168 if (!VerboseVerbose)
2184 Buffer, 0, Buffer.
size(), Diags);
2188 Diags->emplace_back(SM, Pat.
getCheckTy(), Loc, MatchTy, NoteRange,
2193 assert(!HasError &&
"expected to report more diagnostics for error");
2199 if (!HasPatternError) {
2200 std::string Message =
formatv(
"{0}: {1} string not found in input",
2202 (ExpectedMatch ?
"expected" :
"excluded"))
2211 "scanning from here");
2229 std::vector<FileCheckDiag> *Diags) {
2231 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2232 std::move(MatchResult), Req, Diags);
2233 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2240 const char *&FirstNewLine) {
2241 unsigned NumNewLines = 0;
2244 Range = Range.substr(Range.find_first_of(
"\n\r"));
2251 if (Range.size() > 1 && (Range[1] ==
'\n' || Range[1] ==
'\r') &&
2252 (Range[0] != Range[1]))
2253 Range = Range.substr(1);
2254 Range = Range.substr(1);
2256 if (NumNewLines == 1)
2257 FirstNewLine = Range.begin();
2262 bool IsLabelScanMode,
size_t &MatchLen,
2264 std::vector<FileCheckDiag> *Diags)
const {
2266 std::vector<const Pattern *> NotStrings;
2272 if (!IsLabelScanMode) {
2274 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2280 size_t LastMatchEnd = LastPos;
2281 size_t FirstMatchPos = 0;
2292 Pat, i, MatchBuffer,
2293 std::move(MatchResult), Req, Diags)) {
2298 size_t MatchPos = MatchResult.
TheMatch->Pos;
2300 FirstMatchPos = LastPos + MatchPos;
2303 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2306 MatchLen = LastMatchEnd - FirstMatchPos;
2310 if (!IsLabelScanMode) {
2311 size_t MatchPos = FirstMatchPos - LastPos;
2335 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2339 return FirstMatchPos;
2352 const char *FirstNewLine =
nullptr;
2355 if (NumNewLines == 0) {
2357 CheckName +
": is on the same line as previous match");
2359 "'next' match was here");
2361 "previous match ended here");
2365 if (NumNewLines != 1) {
2368 ": is not on the line after the previous match");
2370 "'next' match was here");
2372 "previous match ended here");
2374 "non-matching line after previous match is here");
2386 const char *FirstNewLine =
nullptr;
2389 if (NumNewLines != 0) {
2392 "-SAME: is not on the same line as the previous match");
2394 "'next' match was here");
2396 "previous match ended here");
2404 const std::vector<const Pattern *> &NotStrings,
2406 std::vector<FileCheckDiag> *Diags)
const {
2407 bool DirectiveFail =
false;
2413 std::move(MatchResult), Req, Diags)) {
2415 DirectiveFail =
true;
2419 return DirectiveFail;
2423 std::vector<const Pattern *> &NotStrings,
2425 std::vector<FileCheckDiag> *Diags)
const {
2430 size_t StartPos = 0;
2439 std::list<MatchRange> MatchRanges;
2444 PatItr != PatEnd; ++PatItr) {
2448 "Invalid CHECK-DAG or CHECK-NOT!");
2451 NotStrings.push_back(&
Pat);
2458 size_t MatchLen = 0, MatchPos = StartPos;
2462 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2470 std::move(MatchResult), Req, Diags)) {
2476 MatchLen = MatchResult.
TheMatch->Len;
2479 MatchPos += MatchResult.
TheMatch->Pos;
2480 MatchRange M{MatchPos, MatchPos + MatchLen};
2485 if (MatchRanges.empty())
2486 MatchRanges.insert(MatchRanges.end(), M);
2488 auto Block = MatchRanges.begin();
2495 bool Overlap =
false;
2496 for (;
MI != ME; ++
MI) {
2497 if (M.Pos <
MI->End) {
2500 Overlap =
MI->Pos < M.End;
2506 MatchRanges.insert(
MI, M);
2516 SMRange OldRange(OldStart, OldEnd);
2518 "match discarded, overlaps earlier DAG match here",
2521 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2522 for (
auto I = Diags->rbegin(),
E = Diags->rend();
2523 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
2536 if (std::next(PatItr) == PatEnd ||
2538 if (!NotStrings.empty()) {
2543 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2544 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2551 StartPos = MatchRanges.rbegin()->End;
2553 MatchRanges.clear();
2562 for (
StringRef Prefix : SuppliedPrefixes) {
2563 if (Prefix.empty()) {
2564 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2568 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2569 if (!Validator.
match(Prefix)) {
2570 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2571 <<
"letter and contain only alphanumeric characters, hyphens, and "
2572 <<
"underscores: '" << Prefix <<
"'\n";
2575 if (!UniquePrefixes.
insert(Prefix).second) {
2576 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2577 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2592 UniquePrefixes.
insert(Prefix);
2596 UniquePrefixes.
insert(Prefix);
2628 PrefixRegexStr.
append(Prefix);
2631 return Regex(PrefixRegexStr);
2636 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2637 "Overriding defined variable with command-line variable definitions");
2639 if (CmdlineDefines.
empty())
2647 std::string CmdlineDefsDiag;
2649 for (
StringRef CmdlineDef : CmdlineDefines) {
2650 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2651 size_t EqIdx = CmdlineDef.find(
'=');
2653 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2657 if (CmdlineDef[0] ==
'#') {
2661 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2662 std::string SubstitutionStr = std::string(CmdlineDef);
2663 SubstitutionStr[EqIdx] =
':';
2665 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2666 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2668 CmdlineDefsDiag += DefPrefix;
2670 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2671 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2678 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2680 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2683 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2684 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2685 CmdlineDefIndices.second);
2686 if (CmdlineDef.
empty()) {
2690 "missing equal sign in global definition"));
2695 if (CmdlineDef[0] ==
'#') {
2699 std::optional<NumericVariable *> DefinedNumericVariable;
2702 DefinedNumericVariable,
false,
2703 std::nullopt,
this, SM);
2704 if (!ExpressionResult) {
2708 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2719 assert(DefinedNumericVariable &&
"No variable defined");
2720 (*DefinedNumericVariable)->setValue(*
Value);
2723 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2724 *DefinedNumericVariable;
2727 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2728 StringRef CmdlineName = CmdlineNameVal.first;
2729 StringRef OrigCmdlineName = CmdlineName;
2732 if (!ParseVarResult) {
2739 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2742 SM, OrigCmdlineName,
2743 "invalid name in string variable definition '" +
2744 OrigCmdlineName +
"'"));
2751 if (GlobalNumericVariableTable.contains(
Name)) {
2754 "numeric variable with name '" +
2755 Name +
"' already exists"));
2758 GlobalVariableTable.insert(CmdlineNameVal);
2765 DefinedVariableTable[
Name] =
true;
2775 if (Var.first()[0] !=
'$')
2776 LocalPatternVars.
push_back(Var.first());
2784 for (
const auto &Var : GlobalNumericVariableTable)
2785 if (Var.first()[0] !=
'$') {
2786 Var.getValue()->clearValue();
2787 LocalNumericVars.
push_back(Var.first());
2790 for (
const auto &Var : LocalPatternVars)
2791 GlobalVariableTable.erase(Var);
2792 for (
const auto &Var : LocalNumericVars)
2793 GlobalNumericVariableTable.erase(Var);
2797 std::vector<FileCheckDiag> *Diags) {
2798 bool ChecksFailed =
false;
2800 unsigned i = 0, j = 0, e = CheckStrings->size();
2804 CheckRegion = Buffer;
2813 size_t MatchLabelLen = 0;
2814 size_t MatchLabelPos =
2815 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2820 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2821 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2829 PatternContext->clearLocalVars();
2831 for (; i != j; ++i) {
2836 size_t MatchLen = 0;
2838 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2841 ChecksFailed =
true;
2846 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2854 return !ChecksFailed;
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, Regex &PrefixRE, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
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 int64_t getAsSigned(uint64_t UnsignedValue)
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 bool IsPartOfWord(char c)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringSet - A set-like wrapper for the StringMap.
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< ExpressionValue > eval() const override
Evaluates the value of the binary operation represented by this AST, using EvalBinop on the result of...
std::string getDescription(StringRef Prefix) const
bool isLiteralMatch() const
std::string getModifiersDescription() const
FileCheckType & setCount(int C)
Class to represent an error holding a diagnostic with location information used when printing it.
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< ExpressionValue > eval() const =0
Evaluates and.
StringRef getExpressionStr() const
Class representing a numeric value.
ExpressionValue getAbsolute() const
bool isNegative() const
Returns true if value is signed and negative, false otherwise.
Expected< int64_t > getSignedValue() const
Expected< uint64_t > getUnsignedValue() 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...
Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
void createLineVariable()
Create @LINE pseudo variable.
Expected< StringRef > getPatternVarValue(StringRef VarName)
void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
FileCheck(FileCheckRequest Req)
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...
bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
Regex buildCheckPrefixRegex()
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
Expected< std::string > getResult() const override
Expected< ExpressionValue > eval() const override
Class representing a numeric variable and its associated current value.
ExpressionFormat getImplicitFormat() const
std::optional< ExpressionValue > getValue() const
void setValue(ExpressionValue 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...
std::optional< size_t > getDefLineNumber() const
This is a utility class that provides an abstraction for the common functionality between Instruction...
Class to represent an overflow error that might result when manipulating a value.
static Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
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 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...
void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
static bool isValidVarNameStart(char C)
Check::FileCheckType getCheckTy() const
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 std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
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...
void append(StringRef RHS)
Append from a StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
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.
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.
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).
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.
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.
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 startswith(StringRef Prefix) const
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.
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.
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.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Expected< std::string > getResult() const override
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
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...
StringRef FromStr
The string that needs to be substituted for something else.
virtual Expected< std::string > getResult() const =0
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.
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.
#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.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
APInt operator*(APInt a, uint64_t RHS)
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.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
std::enable_if_t< std::is_unsigned_v< T >, T > AbsoluteDifference(T X, T Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
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.
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
std::enable_if_t< std::is_signed_v< T >, std::optional< T > > checkedSub(T LHS, T RHS)
Subtract two signed integers LHS and RHS.
InstructionCost operator/(const InstructionCost &LHS, const InstructionCost &RHS)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
APInt operator+(APInt a, const APInt &b)
void consumeError(Error Err)
Consume a Error without doing anything.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange, StringRef Note="")
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 ...
Contains info about various FileCheck options.
bool IsDefaultCheckPrefix
std::vector< StringRef > GlobalDefines
bool NoCanonicalizeWhiteSpace
std::vector< StringRef > ImplicitCheckNot
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.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const Pattern * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches "dag strings" and their mixed "not strings".
SMLoc Loc
The location in the match file that the check string was specified.
StringRef Prefix
Which prefix name this check matched.
std::vector< Pattern > DagNotStrings
All of the strings that are disallowed from occurring between this match string and the previous one ...
bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const Pattern * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
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".
std::optional< Match > TheMatch
Parsing information about a variable.