51 auto CreatePrecisionRegex = [&](
StringRef S) {
52 return (
Twine(AlternateFormPrefix) + S +
Twine(
'{') +
Twine(Precision) +
60 return CreatePrecisionRegex(
"([1-9][0-9]*)?[0-9]");
61 return std::string(
"[0-9]+");
64 return CreatePrecisionRegex(
"-?([1-9][0-9]*)?[0-9]");
65 return std::string(
"-?[0-9]+");
68 return CreatePrecisionRegex(
"([1-9A-F][0-9A-F]*)?[0-9A-F]");
69 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9A-F]+")).str();
72 return CreatePrecisionRegex(
"([1-9a-f][0-9a-f]*)?[0-9a-f]");
73 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9a-f]+")).str();
76 "trying to match value with invalid format");
83 return make_error<OverflowError>();
86 bool UpperCase =
false;
104 "trying to match value with invalid format");
106 IntValue.
abs().
toString(AbsoluteValueStr, Radix,
false,
112 if (Precision > AbsoluteValueStr.
size()) {
113 unsigned LeadingZeros = Precision - AbsoluteValueStr.
size();
114 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
115 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
119 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
131 APInt Result = AbsVal;
140 bool Negative = StrVal.consume_front(
"-");
142 bool MissingFormPrefix =
143 !ValueIsSigned && AlternateForm && !StrVal.consume_front(
"0x");
144 (void)MissingFormPrefix;
145 assert(!MissingFormPrefix &&
"missing alternate form prefix");
147 [[maybe_unused]]
bool ParseFailure =
148 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
152 assert(!ParseFailure &&
"unable to represent numeric value");
153 return toSigned(ResultValue, Negative);
157 const APInt &RightOperand,
bool &Overflow) {
158 return LeftOperand.
sadd_ov(RightOperand, Overflow);
162 const APInt &RightOperand,
bool &Overflow) {
163 return LeftOperand.
ssub_ov(RightOperand, Overflow);
167 const APInt &RightOperand,
bool &Overflow) {
168 return LeftOperand.
smul_ov(RightOperand, Overflow);
172 const APInt &RightOperand,
bool &Overflow) {
174 if (RightOperand.
isZero())
175 return make_error<OverflowError>();
177 return LeftOperand.
sdiv_ov(RightOperand, Overflow);
181 const APInt &RightOperand,
bool &Overflow) {
183 return LeftOperand.
slt(RightOperand) ? RightOperand : LeftOperand;
187 const APInt &RightOperand,
bool &Overflow) {
189 if (
cantFail(
exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
209 if (!MaybeLeftOp || !MaybeRightOp) {
215 return std::move(Err);
218 APInt LeftOp = *MaybeLeftOp;
219 APInt RightOp = *MaybeRightOp;
224 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
225 LeftOp = LeftOp.
sext(NewBitWidth);
226 RightOp = RightOp.
sext(NewBitWidth);
236 LeftOp = LeftOp.
sext(NewBitWidth);
237 RightOp = RightOp.
sext(NewBitWidth);
245 if (!LeftFormat || !RightFormat) {
251 return std::move(Err);
256 *LeftFormat != *RightFormat)
259 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
260 "' (" + LeftFormat->toString() +
") and '" +
261 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
262 "), need an explicit format specifier");
269 assert(ExpressionPointer->getAST() !=
nullptr &&
270 "Substituting empty expression");
275 return Format.getMatchingString(*EvaluatedValue);
294 bool IsPseudo = Str[0] ==
'@';
297 if (Str[0] ==
'$' || IsPseudo)
303 for (
size_t E = Str.size();
I !=
E; ++
I)
305 if (Str[
I] !=
'_' && !isAlnum(Str[
I]))
339 if (ParseVarResult->IsPseudo)
341 SM,
Name,
"definition of pseudo numeric variable unsupported");
347 SM,
Name,
"string variable with name '" +
Name +
"' already exists");
352 SM, Expr,
"unexpected characters after numeric variable name");
355 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
356 if (VarTableIter !=
Context->GlobalNumericVariableTable.end()) {
357 DefinedNumericVariable = VarTableIter->second;
360 SM, Expr,
"format different from previous variable definition");
362 DefinedNumericVariable =
363 Context->makeNumericVariable(
Name, ImplicitFormat, LineNumber);
365 return DefinedNumericVariable;
369 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
371 if (IsPseudo && !
Name.equals(
"@LINE"))
373 SM,
Name,
"invalid pseudo numeric variable '" +
Name +
"'");
383 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
385 if (VarTableIter !=
Context->GlobalNumericVariableTable.end())
394 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
397 "numeric variable '" +
Name +
398 "' defined earlier in the same CHECK directive");
404 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
408 if (AO != AllowedOperand::Any)
410 SM, Expr,
"parenthesized expression not permitted here");
411 return parseParenExpr(Expr, LineNumber, Context, SM);
414 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
418 if (ParseVarResult) {
421 if (AO != AllowedOperand::Any)
423 "unexpected function call");
425 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
429 return parseNumericVariableUse(ParseVarResult->Name,
430 ParseVarResult->IsPseudo, LineNumber,
434 if (AO == AllowedOperand::LineVar)
444 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
447 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
453 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
458Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
471 Expr, AllowedOperand::Any,
false, LineNumber,
476 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
477 LineNumber, Context, SM);
481 return SubExprResult;
485 "missing ')' at end of nested expression");
487 return SubExprResult;
492 std::unique_ptr<ExpressionAST> LeftOp,
493 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
496 if (RemainingExpr.
empty())
497 return std::move(LeftOp);
518 if (RemainingExpr.
empty())
520 "missing operand in expression");
523 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
525 parseNumericOperand(RemainingExpr, AO,
false,
526 LineNumber, Context, SM);
528 return RightOpResult;
531 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
532 std::move(*RightOpResult));
537 std::optional<size_t> LineNumber,
553 SM, FuncName,
Twine(
"call to undefined function '") + FuncName +
"'");
567 Expr, AllowedOperand::Any,
false, LineNumber,
569 while (Arg && !Expr.
empty()) {
576 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg),
false, LineNumber,
583 Args.push_back(std::move(*Arg));
597 "missing ')' at end of call expression");
599 const unsigned NumArgs =
Args.size();
601 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
606 Twine(
"function '") + FuncName +
607 Twine(
"' takes 2 arguments but ") +
608 Twine(NumArgs) +
" given");
612 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
613 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
615 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
617 DefinedNumericVariable = std::nullopt;
619 unsigned Precision = 0;
622 size_t FormatSpecEnd = Expr.
find(
',');
623 size_t FunctionStart = Expr.
find(
'(');
624 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
631 "invalid matching format specification in expression");
641 "invalid precision in format specifier");
644 if (!FormatExpr.
empty()) {
659 Precision, AlternateForm);
663 Precision, AlternateForm);
667 "invalid format specifier in expression");
674 SM, AlternateFormFlagLoc,
675 "alternate form only supported for hex values");
678 if (!FormatExpr.
empty())
681 "invalid matching format specification in expression");
685 size_t DefEnd = Expr.
find(
':');
687 DefExpr = Expr.
substr(0, DefEnd);
688 Expr = Expr.
substr(DefEnd + 1);
693 bool HasParsedValidConstraint =
false;
695 HasParsedValidConstraint =
true;
700 if (HasParsedValidConstraint)
702 SM, Expr,
"empty numeric expression should not have a constraint");
709 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
711 Expr, AO, !HasParsedValidConstraint, LineNumber,
Context, SM);
712 while (ParseResult && !Expr.
empty()) {
713 ParseResult = parseBinop(OuterBinOpExpr, Expr, std::move(*ParseResult),
714 IsLegacyLineExpr, LineNumber,
Context, SM);
716 if (ParseResult && IsLegacyLineExpr && !Expr.
empty())
719 "unexpected characters at end of expression '" + Expr +
"'");
723 ExpressionASTPointer = std::move(*ParseResult);
733 else if (ExpressionASTPointer) {
735 ExpressionASTPointer->getImplicitFormat(SM);
743 std::unique_ptr<Expression> ExpressionPointer =
744 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
750 DefExpr,
Context, LineNumber, ExpressionPointer->getFormat(), SM);
754 DefinedNumericVariable = *ParseResult;
757 return std::move(ExpressionPointer);
769 while (!PatternStr.
empty() &&
770 (PatternStr.
back() ==
' ' || PatternStr.
back() ==
'\t'))
771 PatternStr = PatternStr.
substr(0, PatternStr.
size() - 1);
776 "found empty check string with prefix '" + Prefix +
":'");
783 "found non-empty check string for empty check with prefix '" + Prefix +
795 FixedStr = PatternStr;
800 if (!MatchFullLinesHere &&
801 (PatternStr.
size() < 2 ||
803 FixedStr = PatternStr;
807 if (MatchFullLinesHere) {
815 unsigned CurParen = 1;
819 while (!PatternStr.
empty()) {
823 size_t End = PatternStr.
find(
"}}");
827 "found start of regex string with no end '}}'");
838 if (AddRegExToRegEx(PatternStr.
substr(2,
End - 2), CurParen, SM))
860 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
867 "Invalid substitution block, no ]] found");
873 PatternStr = UnparsedPatternStr.
substr(
End + 2);
875 bool IsDefinition =
false;
876 bool SubstNeeded =
false;
879 bool IsLegacyLineExpr =
false;
883 std::string WildcardRegexp;
884 size_t SubstInsertIdx = RegExStr.size();
888 size_t VarEndIdx = MatchStr.
find(
':');
900 if (!ParseVarResult) {
905 bool IsPseudo = ParseVarResult->IsPseudo;
908 SubstNeeded = !IsDefinition;
913 "invalid name in string variable definition");
919 if (
Context->GlobalNumericVariableTable.contains(
Name)) {
922 "numeric variable with name '" +
Name +
"' already exists");
926 MatchRegexp = MatchStr;
929 MatchStr = OrigMatchStr;
930 IsLegacyLineExpr = IsNumBlock =
true;
932 if (!MatchStr.
empty()) {
935 "invalid name in string variable use");
944 std::unique_ptr<Expression> ExpressionPointer;
945 std::optional<NumericVariable *> DefinedNumericVariable;
949 IsLegacyLineExpr, LineNumber,
Context,
955 ExpressionPointer = std::move(*ParseResult);
956 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
957 if (DefinedNumericVariable) {
959 DefName = (*DefinedNumericVariable)->getName();
966 MatchRegexp = WildcardRegexp;
976 NumericVariableMatch NumericVariableDefinition = {
977 *DefinedNumericVariable, CurParen};
978 NumericVariableDefs[DefName] = NumericVariableDefinition;
983 Context->GlobalNumericVariableTable[DefName] =
984 *DefinedNumericVariable;
986 VariableDefs[DefName] = CurParen;
993 Context->DefinedVariableTable[DefName] =
true;
999 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1010 if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
1011 unsigned CaptureParenGroup = VariableDefs[SubstStr];
1012 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1015 "Can't back-reference more than 9 variables");
1018 AddBackrefToRegEx(CaptureParenGroup);
1024 ?
Context->makeNumericSubstitution(
1025 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1026 :
Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1036 size_t FixedMatchEnd =
1037 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1039 PatternStr = PatternStr.
substr(FixedMatchEnd);
1042 if (MatchFullLinesHere) {
1054 if (!R.isValid(
Error)) {
1056 "invalid regex: " +
Error);
1060 RegExStr += RS.
str();
1061 CurParen += R.getNumMatches();
1065void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1066 assert(BackrefNum >= 1 && BackrefNum <= 9 &&
"Invalid backref number");
1067 std::string Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1068 RegExStr += Backref;
1078 if (!FixedStr.
empty()) {
1082 return make_error<NotFoundError>();
1092 if (!Substitutions.empty()) {
1095 Context->LineVariable->setValue(
1096 APInt(
sizeof(*LineNumber) * 8, *LineNumber));
1098 size_t InsertOffset = 0;
1114 return ErrorDiagnostic::get(
1115 SM, Substitution->getFromString(),
1116 "unable to substitute variable or "
1117 "numeric expression: overflow error");
1120 return ErrorDiagnostic::get(SM, E.getVarName(),
1129 InsertOffset +=
Value->size();
1132 return std::move(Errs);
1135 RegExToMatch = TmpStr;
1142 if (!
Regex(RegExToMatch, Flags).
match(Buffer, &MatchInfo))
1143 return make_error<NotFoundError>();
1146 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1150 for (
const auto &VariableDef : VariableDefs) {
1151 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1152 Context->GlobalVariableTable[VariableDef.first] =
1153 MatchInfo[VariableDef.second];
1161 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1162 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
1165 for (
const auto &NumericVariableDef : NumericVariableDefs) {
1166 const NumericVariableMatch &NumericVariableMatch =
1167 NumericVariableDef.getValue();
1168 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1169 assert(CaptureParenGroup < MatchInfo.
size() &&
"Internal paren error");
1171 NumericVariableMatch.DefinedNumericVariable;
1173 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1182unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1190 if (ExampleString.empty())
1191 ExampleString = RegExStr;
1195 BufferPrefix = BufferPrefix.
split(
'\n').first;
1202 std::vector<FileCheckDiag> *Diags)
const {
1204 if (!Substitutions.empty()) {
1211 if (!MatchedValue) {
1225 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1226 SMRange(Range.Start, Range.Start),
OS.str());
1235 std::vector<FileCheckDiag> *Diags)
const {
1236 if (VariableDefs.empty() && NumericVariableDefs.
empty())
1244 for (
const auto &VariableDef : VariableDefs) {
1246 VC.Name = VariableDef.first;
1253 for (
const auto &VariableDef : NumericVariableDefs) {
1255 VC.Name = VariableDef.getKey();
1256 std::optional<StringRef> StrValue =
1257 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1267 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1270 assert(
A.Range.Start !=
B.Range.Start &&
1271 "unexpected overlapping variable captures");
1272 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1275 for (
const VarCapture &VC : VarCaptures) {
1278 OS <<
"captured var \"" << VC.Name <<
"\"";
1280 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range,
OS.str());
1289 StringRef Buffer,
size_t Pos,
size_t Len,
1290 std::vector<FileCheckDiag> *Diags,
1291 bool AdjustPrevDiags =
false) {
1296 if (AdjustPrevDiags) {
1297 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1298 for (
auto I = Diags->rbegin(),
E = Diags->rend();
1299 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
1300 I->MatchTy = MatchTy;
1302 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
1308 std::vector<FileCheckDiag> *Diags)
const {
1313 size_t NumLinesForward = 0;
1315 double BestQuality = 0;
1318 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1319 if (Buffer[i] ==
'\n')
1324 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1329 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1330 double Quality = Distance + (NumLinesForward / 100.);
1334 BestQuality = Quality;
1346 "possible intended match here");
1355 auto VarIter = GlobalVariableTable.find(VarName);
1356 if (VarIter == GlobalVariableTable.end())
1357 return make_error<UndefVarError>(VarName);
1359 return VarIter->second;
1362template <
class... Types>
1364 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1365 return NumericVariables.back().get();
1369FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1371 Substitutions.push_back(
1372 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1373 return Substitutions.back().get();
1376Substitution *FileCheckPatternContext::makeNumericSubstitution(
1379 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1380 this, ExpressionStr, std::move(
Expression), InsertIdx));
1381 return Substitutions.back().get();
1388 size_t BracketDepth = 0;
1390 while (!Str.empty()) {
1391 if (Str.startswith(
"]]") && BracketDepth == 0)
1393 if (Str[0] ==
'\\') {
1395 Str = Str.substr(2);
1405 if (BracketDepth == 0) {
1408 "missing closing \"]\" for regex variable");
1414 Str = Str.substr(1);
1429 if (
Ptr <=
End - 2 &&
Ptr[0] ==
'\r' &&
Ptr[1] ==
'\n') {
1442 while (
Ptr + 1 !=
End && (
Ptr[1] ==
' ' ||
Ptr[1] ==
'\t'))
1455 : CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy),
Note(
Note) {
1465 return (isAlnum(c) || c ==
'-' || c ==
'_');
1469 assert(Count > 0 &&
"zero and negative counts are not supported");
1471 "count supported only for plain CHECK directives");
1477 if (Modifiers.none())
1482 if (isLiteralMatch())
1490 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1491 return (Prefix + Str + getModifiersDescription()).str();
1498 return "misspelled";
1501 return WithModifiers(
"-COUNT");
1502 return WithModifiers(
"");
1504 return WithModifiers(
"-NEXT");
1506 return WithModifiers(
"-SAME");
1508 return WithModifiers(
"-NOT");
1510 return WithModifiers(
"-DAG");
1512 return WithModifiers(
"-LABEL");
1514 return WithModifiers(
"-EMPTY");
1516 return std::string(Prefix);
1518 return "implicit EOF";
1527static std::pair<Check::FileCheckType, StringRef>
1530 if (Buffer.
size() <= Prefix.size())
1543 -> std::pair<Check::FileCheckType, StringRef> {
1552 Rest = Rest.
ltrim();
1554 Ret.setLiteralMatch();
1558 Rest = Rest.
ltrim();
1568 if (Rest.
front() ==
'{')
1581 if (Count <= 0 || Count > INT32_MAX)
1583 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1585 return ConsumeModifiers(
1617static std::pair<Check::FileCheckType, StringRef>
1619 bool Misspelled =
false;
1656static std::pair<StringRef, StringRef>
1658 StringRef &Buffer,
unsigned &LineNumber,
1662 while (!Buffer.
empty()) {
1664 if (!PrefixRE.
match(Buffer, &Matches))
1672 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1673 "Prefix doesn't start inside of buffer!");
1674 size_t Loc = Prefix.data() - Buffer.
data();
1677 LineNumber += Skipped.
count(
'\n');
1687 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1691 return {Prefix, AfterSuffix};
1705 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1707 LineVariable = makeNumericVariable(
1709 GlobalNumericVariableTable[LineName] = LineVariable;
1720 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1721 if (ImpPatBufferIDRange)
1722 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1725 PatternContext->defineCmdlineVariables(Req.
GlobalDefines, SM);
1731 PatternContext->createLineVariable();
1733 std::vector<Pattern> ImplicitNegativeChecks;
1737 std::string Prefix =
"-implicit-check-not='";
1738 std::string Suffix =
"'";
1740 (Prefix + PatternString + Suffix).str(),
"command line");
1743 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1745 if (ImpPatBufferIDRange) {
1746 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1747 ImpPatBufferIDRange->first = BufferID;
1748 ImpPatBufferIDRange->second = BufferID + 1;
1750 assert(BufferID == ImpPatBufferIDRange->second &&
1751 "expected consecutive source buffer IDs");
1752 ++ImpPatBufferIDRange->second;
1756 ImplicitNegativeChecks.push_back(
1758 ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
1759 "IMPLICIT-CHECK", SM, Req);
1762 std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
1766 unsigned LineNumber = 1;
1768 std::set<StringRef> PrefixesNotFound(Req.
CheckPrefixes.begin(),
1770 const size_t DistinctPrefixes = PrefixesNotFound.size();
1777 std::tie(UsedPrefix, AfterSuffix) =
1779 if (UsedPrefix.
empty())
1782 PrefixesNotFound.erase(UsedPrefix);
1785 "Failed to move Buffer's start forward, or pointed prefix outside "
1789 "Parsing after suffix doesn't start inside of buffer!");
1792 const char *UsedPrefixStart = UsedPrefix.
data();
1802 AfterSuffix.
data() - UsedPrefix.
data());
1805 "misspelled directive '" + UsedDirective +
"'");
1812 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1819 "invalid count in -COUNT specification on prefix '" +
1837 Buffer = Buffer.
substr(EOL);
1844 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1845 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1852 "found '" + UsedPrefix +
"-LABEL:'"
1853 " with variable definition or use");
1860 CheckStrings->empty()) {
1866 "found '" + UsedPrefix +
"-" +
Type +
1867 "' without previous '" + UsedPrefix +
": line");
1873 DagNotMatches.push_back(
P);
1878 CheckStrings->emplace_back(
P, UsedPrefix, PatternLoc);
1879 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
1880 DagNotMatches = ImplicitNegativeChecks;
1885 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1886 const bool SomePrefixesUnexpectedlyNotUsed =
1888 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1890 errs() <<
"error: no check strings found with prefix"
1891 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
1893 for (
StringRef MissingPrefix : PrefixesNotFound) {
1896 errs() <<
"\'" << MissingPrefix <<
":'";
1905 if (!DagNotMatches.empty()) {
1906 CheckStrings->emplace_back(
1909 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
1922 std::vector<FileCheckDiag> *Diags) {
1924 bool HasError = !ExpectedMatch || MatchResult.
TheError;
1925 bool PrintDiag =
true;
1949 assert(!HasError &&
"expected to report more diagnostics for error");
1954 std::string Message =
formatv(
"{0}: {1} string found in input",
1956 (ExpectedMatch ?
"expected" :
"excluded"))
1959 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
1976 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
1977 FileCheckDiag::MatchFoundErrorNote,
1978 E.getRange(), E.getMessage().str());
1990 bool VerboseVerbose,
1991 std::vector<FileCheckDiag> *Diags) {
1993 bool HasError = ExpectedMatch;
1994 bool HasPatternError =
false;
2000 std::move(MatchError),
2002 HasError = HasPatternError =
true;
2012 bool PrintDiag =
true;
2014 if (!VerboseVerbose)
2030 Buffer, 0, Buffer.
size(), Diags);
2034 Diags->emplace_back(SM, Pat.
getCheckTy(), Loc, MatchTy, NoteRange,
2039 assert(!HasError &&
"expected to report more diagnostics for error");
2045 if (!HasPatternError) {
2046 std::string Message =
formatv(
"{0}: {1} string not found in input",
2048 (ExpectedMatch ?
"expected" :
"excluded"))
2057 "scanning from here");
2075 std::vector<FileCheckDiag> *Diags) {
2077 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2078 std::move(MatchResult), Req, Diags);
2079 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2086 const char *&FirstNewLine) {
2087 unsigned NumNewLines = 0;
2090 Range = Range.substr(Range.find_first_of(
"\n\r"));
2097 if (Range.size() > 1 && (Range[1] ==
'\n' || Range[1] ==
'\r') &&
2098 (Range[0] != Range[1]))
2099 Range = Range.substr(1);
2100 Range = Range.substr(1);
2102 if (NumNewLines == 1)
2103 FirstNewLine = Range.begin();
2108 bool IsLabelScanMode,
size_t &MatchLen,
2110 std::vector<FileCheckDiag> *Diags)
const {
2112 std::vector<const Pattern *> NotStrings;
2118 if (!IsLabelScanMode) {
2120 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2126 size_t LastMatchEnd = LastPos;
2127 size_t FirstMatchPos = 0;
2138 Pat, i, MatchBuffer,
2139 std::move(MatchResult), Req, Diags)) {
2144 size_t MatchPos = MatchResult.
TheMatch->Pos;
2146 FirstMatchPos = LastPos + MatchPos;
2149 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2152 MatchLen = LastMatchEnd - FirstMatchPos;
2156 if (!IsLabelScanMode) {
2157 size_t MatchPos = FirstMatchPos - LastPos;
2181 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2185 return FirstMatchPos;
2198 const char *FirstNewLine =
nullptr;
2201 if (NumNewLines == 0) {
2203 CheckName +
": is on the same line as previous match");
2205 "'next' match was here");
2207 "previous match ended here");
2211 if (NumNewLines != 1) {
2214 ": is not on the line after the previous match");
2216 "'next' match was here");
2218 "previous match ended here");
2220 "non-matching line after previous match is here");
2232 const char *FirstNewLine =
nullptr;
2235 if (NumNewLines != 0) {
2238 "-SAME: is not on the same line as the previous match");
2240 "'next' match was here");
2242 "previous match ended here");
2250 const std::vector<const Pattern *> &NotStrings,
2252 std::vector<FileCheckDiag> *Diags)
const {
2253 bool DirectiveFail =
false;
2259 std::move(MatchResult), Req, Diags)) {
2261 DirectiveFail =
true;
2265 return DirectiveFail;
2269 std::vector<const Pattern *> &NotStrings,
2271 std::vector<FileCheckDiag> *Diags)
const {
2276 size_t StartPos = 0;
2285 std::list<MatchRange> MatchRanges;
2290 PatItr != PatEnd; ++PatItr) {
2294 "Invalid CHECK-DAG or CHECK-NOT!");
2297 NotStrings.push_back(&
Pat);
2304 size_t MatchLen = 0, MatchPos = StartPos;
2308 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2316 std::move(MatchResult), Req, Diags)) {
2322 MatchLen = MatchResult.
TheMatch->Len;
2325 MatchPos += MatchResult.
TheMatch->Pos;
2326 MatchRange M{MatchPos, MatchPos + MatchLen};
2331 if (MatchRanges.empty())
2332 MatchRanges.insert(MatchRanges.end(), M);
2334 auto Block = MatchRanges.begin();
2341 bool Overlap =
false;
2342 for (;
MI != ME; ++
MI) {
2343 if (M.Pos <
MI->End) {
2346 Overlap =
MI->Pos < M.End;
2352 MatchRanges.insert(
MI, M);
2362 SMRange OldRange(OldStart, OldEnd);
2364 "match discarded, overlaps earlier DAG match here",
2367 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2368 for (
auto I = Diags->rbegin(),
E = Diags->rend();
2369 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
2382 if (std::next(PatItr) == PatEnd ||
2384 if (!NotStrings.empty()) {
2389 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2390 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2397 StartPos = MatchRanges.rbegin()->End;
2399 MatchRanges.clear();
2408 for (
StringRef Prefix : SuppliedPrefixes) {
2409 if (Prefix.empty()) {
2410 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2414 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2415 if (!Validator.
match(Prefix)) {
2416 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2417 <<
"letter and contain only alphanumeric characters, hyphens, and "
2418 <<
"underscores: '" << Prefix <<
"'\n";
2421 if (!UniquePrefixes.
insert(Prefix).second) {
2422 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2423 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2438 UniquePrefixes.
insert(Prefix);
2442 UniquePrefixes.
insert(Prefix);
2474 PrefixRegexStr.
append(Prefix);
2477 return Regex(PrefixRegexStr);
2482 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2483 "Overriding defined variable with command-line variable definitions");
2485 if (CmdlineDefines.
empty())
2493 std::string CmdlineDefsDiag;
2495 for (
StringRef CmdlineDef : CmdlineDefines) {
2496 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2497 size_t EqIdx = CmdlineDef.find(
'=');
2499 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2503 if (CmdlineDef[0] ==
'#') {
2507 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2508 std::string SubstitutionStr = std::string(CmdlineDef);
2509 SubstitutionStr[EqIdx] =
':';
2511 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2512 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2514 CmdlineDefsDiag += DefPrefix;
2516 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2517 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2524 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2526 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2529 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2530 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2531 CmdlineDefIndices.second);
2532 if (CmdlineDef.
empty()) {
2536 "missing equal sign in global definition"));
2541 if (CmdlineDef[0] ==
'#') {
2545 std::optional<NumericVariable *> DefinedNumericVariable;
2548 DefinedNumericVariable,
false,
2549 std::nullopt,
this, SM);
2550 if (!ExpressionResult) {
2554 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2565 assert(DefinedNumericVariable &&
"No variable defined");
2566 (*DefinedNumericVariable)->setValue(*
Value);
2569 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2570 *DefinedNumericVariable;
2573 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2574 StringRef CmdlineName = CmdlineNameVal.first;
2575 StringRef OrigCmdlineName = CmdlineName;
2578 if (!ParseVarResult) {
2585 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2588 SM, OrigCmdlineName,
2589 "invalid name in string variable definition '" +
2590 OrigCmdlineName +
"'"));
2597 if (GlobalNumericVariableTable.contains(
Name)) {
2600 "numeric variable with name '" +
2601 Name +
"' already exists"));
2604 GlobalVariableTable.insert(CmdlineNameVal);
2611 DefinedVariableTable[
Name] =
true;
2621 if (Var.first()[0] !=
'$')
2622 LocalPatternVars.
push_back(Var.first());
2630 for (
const auto &Var : GlobalNumericVariableTable)
2631 if (Var.first()[0] !=
'$') {
2632 Var.getValue()->clearValue();
2633 LocalNumericVars.
push_back(Var.first());
2636 for (
const auto &Var : LocalPatternVars)
2637 GlobalVariableTable.erase(Var);
2638 for (
const auto &Var : LocalNumericVars)
2639 GlobalNumericVariableTable.erase(Var);
2643 std::vector<FileCheckDiag> *Diags) {
2644 bool ChecksFailed =
false;
2646 unsigned i = 0, j = 0, e = CheckStrings->size();
2650 CheckRegion = Buffer;
2659 size_t MatchLabelLen = 0;
2660 size_t MatchLabelPos =
2661 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2666 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2667 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2675 PatternContext->clearLocalVars();
2677 for (; i != j; ++i) {
2682 size_t MatchLen = 0;
2684 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2687 ChecksFailed =
true;
2692 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2700 return !ChecksFailed;
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 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 unsigned nextAPIntBitWidth(unsigned BitWidth)
static bool IsPartOfWord(char c)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
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.
APInt sadd_ov(const APInt &RHS, bool &Overflow) const
APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
void toString(SmallVectorImpl< char > &Str, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true) const
Converts an APInt to a string and append it to Str.
APInt smul_ov(const APInt &RHS, bool &Overflow) const
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.
@ APINT_BITS_PER_WORD
Bits in a word.
APInt ssub_ov(const APInt &RHS, bool &Overflow) const
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...
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< 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...
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< 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< APInt > getValue() const
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.
std::optional< int64_t > toSigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an signed constant.
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))...))>
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.
Expected< APInt > exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Performs operation and.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
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 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)
Expected< APInt > exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Expected< APInt > exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
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.
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.